From 84044c3f282cf3dd351ea5a3594fa66ddc6cd600 Mon Sep 17 00:00:00 2001
From: JeongwooSeo <98446924+ShipFriend0516@users.noreply.github.com>
Date: Fri, 27 Jun 2025 15:51:25 +0900
Subject: [PATCH 1/9] =?UTF-8?q?feat:=20=EC=96=B4=EB=93=9C=EB=AF=BC=20?=
=?UTF-8?q?=EB=8C=80=EC=8B=9C=EB=B3=B4=EB=93=9C=EC=97=90=20=EC=8B=9C?=
=?UTF-8?q?=EB=A6=AC=EC=A6=88=20=EA=B4=80=EB=A6=AC=20=ED=83=AD=20=EC=B6=94?=
=?UTF-8?q?=EA=B0=80?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/admin/page.tsx | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/app/admin/page.tsx b/app/admin/page.tsx
index bc1590a..487ce41 100644
--- a/app/admin/page.tsx
+++ b/app/admin/page.tsx
@@ -12,6 +12,7 @@ import GithubLogin from '@/app/entities/common/Button/GithubLogin';
import BubbleBackground from '@/app/entities/common/Background/BubbleBackground';
import { useEffect } from 'react';
import useToast from '@/app/hooks/useToast';
+import { FaBuffer } from 'react-icons/fa6';
const AdminDashboard = () => {
const { data: session } = useSession();
@@ -67,6 +68,13 @@ const AdminDashboard = () => {
bgColor: 'bg-purple-950/20', // 짙은 보라색의 투명도 적용
link: '/admin/analytics',
},
+ {
+ title: '시리즈 관리',
+ icon: ,
+ description: '블로그 시리즈를 관리합니다.',
+ bgColor: 'bg-emerald-950/20', // 짙은 보라색의 투명도 적용
+ link: '/admin/series',
+ },
{
title: '댓글 확인 및 관리',
icon: ,
From 35d77d697baef8803c68ff799684f96a11981d10 Mon Sep 17 00:00:00 2001
From: JeongwooSeo <98446924+ShipFriend0516@users.noreply.github.com>
Date: Fri, 27 Jun 2025 16:27:29 +0900
Subject: [PATCH 2/9] =?UTF-8?q?feat:=20=EC=8B=9C=EB=A6=AC=EC=A6=88=20?=
=?UTF-8?q?=EB=A6=AC=EC=8A=A4=ED=8A=B8,=20=EC=95=84=EC=9D=B4=ED=85=9C=20?=
=?UTF-8?q?=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EC=9E=91=EC=84=B1?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/admin/series/page.tsx | 44 +++++++++++++
app/entities/series/list/AdminSeriesList.tsx | 26 ++++++++
.../series/list/AdminSeriesListItem.tsx | 61 +++++++++++++++++++
3 files changed, 131 insertions(+)
create mode 100644 app/admin/series/page.tsx
create mode 100644 app/entities/series/list/AdminSeriesList.tsx
create mode 100644 app/entities/series/list/AdminSeriesListItem.tsx
diff --git a/app/admin/series/page.tsx b/app/admin/series/page.tsx
new file mode 100644
index 0000000..be4c316
--- /dev/null
+++ b/app/admin/series/page.tsx
@@ -0,0 +1,44 @@
+'use client';
+import { Series } from '@/app/types/Series';
+import useDataFetch, {
+ useDataFetchConfig,
+} from '@/app/hooks/common/useDataFetch';
+import React from 'react';
+import AdminSeriesList from '@/app/entities/series/list/AdminSeriesList';
+const AdminSeriesPage = () => {
+ const getSeriesListConfig: useDataFetchConfig = {
+ url: '/api/series',
+ method: 'GET',
+ config: {
+ params: {
+ compact: 'true',
+ },
+ },
+ };
+
+ const { data: seriesList, loading } =
+ useDataFetch(getSeriesListConfig);
+
+ return (
+
+ 시리즈 관리
+
+ 시리즈를 관리하는 페이지입니다. 시리즈를 추가, 수정, 삭제할 수 있습니다.
+
+
+
+
+
+
+ 등록된 시리즈 목록 ({seriesList?.length || 0})
+
+
+
+
+
+ );
+};
+
+export default AdminSeriesPage;
diff --git a/app/entities/series/list/AdminSeriesList.tsx b/app/entities/series/list/AdminSeriesList.tsx
new file mode 100644
index 0000000..d486661
--- /dev/null
+++ b/app/entities/series/list/AdminSeriesList.tsx
@@ -0,0 +1,26 @@
+import { Series } from '@/app/types/Series';
+import React from 'react';
+import AdminSeriesListItem from '@/app/entities/series/list/AdminSeriesListItem';
+
+interface AdminSeriesListProps {
+ seriesList: Series[] | null | undefined;
+ loading: boolean;
+}
+const AdminSeriesList = ({ loading, seriesList }: AdminSeriesListProps) => {
+ if (loading) {
+ return 로딩 중...
;
+ }
+ if (!seriesList || seriesList.length === 0) {
+ return 등록된 시리즈가 없습니다.
;
+ }
+ return (
+
+ {loading && 로딩 중...
}
+ {seriesList.map((series, index) => (
+
+ ))}
+
+ );
+};
+
+export default AdminSeriesList;
diff --git a/app/entities/series/list/AdminSeriesListItem.tsx b/app/entities/series/list/AdminSeriesListItem.tsx
new file mode 100644
index 0000000..fc90920
--- /dev/null
+++ b/app/entities/series/list/AdminSeriesListItem.tsx
@@ -0,0 +1,61 @@
+import { Series } from '@/app/types/Series';
+import Image from 'next/image';
+import { FaBookOpen, FaCalendar } from 'react-icons/fa';
+import React from 'react';
+
+const AdminSeriesListItem = ({ series }: { series: Series }) => {
+ return (
+
+
+ {series.thumbnailImage ? (
+
+ ) : (
+
+
+
+ )}
+
+
+
+ {series.title}
+
+
+
+
+
+ {new Date(series.date).toLocaleDateString()}
+
+
+
+ {series.posts.length || 0} posts
+
+
+
+
+ {series.description || 'No description available'}
+
+
+
+
+
+
+
+ );
+};
+
+export default AdminSeriesListItem;
From 58f4a30b0aeeb3853a80c6201280fd9c442860cd Mon Sep 17 00:00:00 2001
From: JeongwooSeo <98446924+ShipFriend0516@users.noreply.github.com>
Date: Fri, 27 Jun 2025 16:40:20 +0900
Subject: [PATCH 3/9] =?UTF-8?q?refactor:=20=EA=B8=B0=EC=A1=B4=20=EC=8B=9C?=
=?UTF-8?q?=EB=A6=AC=EC=A6=88=20=EC=83=9D=EC=84=B1=20=EC=98=A4=EB=B2=84?=
=?UTF-8?q?=EB=A0=88=EC=9D=B4=EB=A5=BC=20=EC=88=98=EC=A0=95=20=EB=AA=A8?=
=?UTF-8?q?=EB=93=9C=EB=8F=84=20=EA=B0=80=EB=8A=A5=ED=95=98=EA=B2=8C=20?=
=?UTF-8?q?=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81=20=EB=B0=8F=20=EC=9E=AC?=
=?UTF-8?q?=EC=82=AC=EC=9A=A9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/admin/series/page.tsx | 35 ++++++++++++++--
.../series/CreateSeriesOverlayContainer.tsx | 41 +++++++++++++++----
app/entities/series/api/series.ts | 2 -
app/entities/series/list/AdminSeriesList.tsx | 13 +++++-
.../series/list/AdminSeriesListItem.tsx | 15 ++++++-
5 files changed, 90 insertions(+), 16 deletions(-)
diff --git a/app/admin/series/page.tsx b/app/admin/series/page.tsx
index be4c316..6705b4f 100644
--- a/app/admin/series/page.tsx
+++ b/app/admin/series/page.tsx
@@ -3,8 +3,10 @@ import { Series } from '@/app/types/Series';
import useDataFetch, {
useDataFetchConfig,
} from '@/app/hooks/common/useDataFetch';
-import React from 'react';
+import { useState } from 'react';
import AdminSeriesList from '@/app/entities/series/list/AdminSeriesList';
+import Overlay from '@/app/entities/common/Overlay/Overlay';
+import CreateSeriesOverlayContainer from '@/app/entities/series/CreateSeriesOverlayContainer';
const AdminSeriesPage = () => {
const getSeriesListConfig: useDataFetchConfig = {
url: '/api/series',
@@ -18,6 +20,16 @@ const AdminSeriesPage = () => {
const { data: seriesList, loading } =
useDataFetch(getSeriesListConfig);
+ const [createSeriesOpen, setCreateSeriesOpen] = useState(false);
+ const [toUpdateSeries, setToUpdateSeries] = useState(null);
+ const handleUpdateSeries = (series: Series) => {
+ setCreateSeriesOpen(true);
+ setToUpdateSeries(series);
+ };
+ const handleCloseOverlay = () => {
+ setCreateSeriesOpen(false);
+ setToUpdateSeries(null);
+ };
return (
@@ -26,7 +38,10 @@ const AdminSeriesPage = () => {
시리즈를 관리하는 페이지입니다. 시리즈를 추가, 수정, 삭제할 수 있습니다.
-
@@ -35,8 +50,22 @@ const AdminSeriesPage = () => {
등록된 시리즈 목록 ({seriesList?.length || 0})
-
+
+
+
+
);
};
diff --git a/app/entities/series/CreateSeriesOverlayContainer.tsx b/app/entities/series/CreateSeriesOverlayContainer.tsx
index 4f844e6..f7331a9 100644
--- a/app/entities/series/CreateSeriesOverlayContainer.tsx
+++ b/app/entities/series/CreateSeriesOverlayContainer.tsx
@@ -1,17 +1,23 @@
import { ChangeEvent, useState } from 'react';
-import { createSeries } from '@/app/entities/series/api/series';
+import { createSeries, updateSeries } from '@/app/entities/series/api/series';
import useToast from '@/app/hooks/useToast';
+import { Series } from '@/app/types/Series';
interface CreateSeriesOverlayContainerProps {
setCreateSeriesOpen: (open: boolean) => void;
+ series?: Series;
+ handleCloseOverlay?: () => void;
}
const CreateSeriesOverlayContainer = ({
setCreateSeriesOpen,
+ series,
+ handleCloseOverlay,
}: CreateSeriesOverlayContainerProps) => {
const [seriesTitle, setSeriesTitle] = useState('');
const [seriesDescription, setSeriesDescription] = useState('');
const [seriesThumbnail, setSeriesThumbnail] = useState('');
+ const isEditMode = !!series;
const toast = useToast();
const postSeries = async () => {
@@ -34,10 +40,31 @@ const CreateSeriesOverlayContainer = ({
}
};
+ const editSeries = async () => {
+ try {
+ if (isEditMode) {
+ await updateSeries(series.slug, {
+ title: seriesTitle,
+ description: seriesDescription,
+ thumbnailImage: seriesThumbnail,
+ });
+ }
+ } catch (e) {
+ toast.error('시리즈 수정 중 오류가 발생했습니다.');
+ console.error('시리즈 수정 중 오류 발생', e);
+ } finally {
+ if (handleCloseOverlay) {
+ handleCloseOverlay();
+ } else {
+ setCreateSeriesOpen(false);
+ }
+ }
+ };
+
return (
- 새로운 시리즈 만들기
+ {isEditMode ? '시리즈 수정하기' : '새로운 시리즈 만들기'}
새로운 시리즈를 생성합니다. 제목은 필수로 작성해야합니다.
@@ -53,7 +80,7 @@ const CreateSeriesOverlayContainer = ({
placeholder="시리즈의 이름"
className="w-full p-2.5 border border-gray-300 rounded-md focus:ring-2 focus:ring-emerald-500 focus:border-emerald-500 outline-none transition text-black"
onChange={(e) => setSeriesTitle(e.target.value)}
- value={seriesTitle || ''}
+ value={isEditMode ? series?.title : seriesTitle || ''}
/>
@@ -65,7 +92,7 @@ const CreateSeriesOverlayContainer = ({
placeholder="시리즈의 설명"
className="w-full p-2.5 border border-gray-300 rounded-md focus:ring-2 focus:ring-emerald-500 focus:border-emerald-500 outline-none transition text-black min-h-[100px] resize-y"
onChange={(e) => setSeriesDescription(e.target.value)}
- value={seriesDescription || ''}
+ value={isEditMode ? series?.description : seriesDescription || ''}
/>
@@ -78,7 +105,7 @@ const CreateSeriesOverlayContainer = ({
placeholder="시리즈의 썸네일 링크"
className="w-full p-2.5 border border-gray-300 rounded-md focus:ring-2 focus:ring-emerald-500 focus:border-emerald-500 outline-none transition text-black"
onChange={(e) => setSeriesThumbnail(e.target.value)}
- value={seriesThumbnail || ''}
+ value={isEditMode ? series?.thumbnailImage : seriesThumbnail || ''}
/>
@@ -91,10 +118,10 @@ const CreateSeriesOverlayContainer = ({
취소
- 생성
+ {isEditMode ? '수정' : '생성'}
diff --git a/app/entities/series/api/series.ts b/app/entities/series/api/series.ts
index b9d38cb..5780a4c 100644
--- a/app/entities/series/api/series.ts
+++ b/app/entities/series/api/series.ts
@@ -31,8 +31,6 @@ export const updateSeries = async (
title: string;
description: string;
thumbnailImage: string;
- order: string[];
- posts: string[];
}
) => {
const response = await axios.put(`/api/series/${slug}`, data);
diff --git a/app/entities/series/list/AdminSeriesList.tsx b/app/entities/series/list/AdminSeriesList.tsx
index d486661..134e3cd 100644
--- a/app/entities/series/list/AdminSeriesList.tsx
+++ b/app/entities/series/list/AdminSeriesList.tsx
@@ -5,8 +5,13 @@ import AdminSeriesListItem from '@/app/entities/series/list/AdminSeriesListItem'
interface AdminSeriesListProps {
seriesList: Series[] | null | undefined;
loading: boolean;
+ handleUpdateSeries: (series: Series) => void;
}
-const AdminSeriesList = ({ loading, seriesList }: AdminSeriesListProps) => {
+const AdminSeriesList = ({
+ loading,
+ seriesList,
+ handleUpdateSeries,
+}: AdminSeriesListProps) => {
if (loading) {
return 로딩 중...
;
}
@@ -17,7 +22,11 @@ const AdminSeriesList = ({ loading, seriesList }: AdminSeriesListProps) => {
{loading && 로딩 중...
}
{seriesList.map((series, index) => (
-
+
))}
);
diff --git a/app/entities/series/list/AdminSeriesListItem.tsx b/app/entities/series/list/AdminSeriesListItem.tsx
index fc90920..112340f 100644
--- a/app/entities/series/list/AdminSeriesListItem.tsx
+++ b/app/entities/series/list/AdminSeriesListItem.tsx
@@ -3,7 +3,15 @@ import Image from 'next/image';
import { FaBookOpen, FaCalendar } from 'react-icons/fa';
import React from 'react';
-const AdminSeriesListItem = ({ series }: { series: Series }) => {
+interface AdminSeriesListItemProps {
+ series: Series;
+ handleUpdateSeries: (series: Series) => void;
+}
+
+const AdminSeriesListItem = ({
+ series,
+ handleUpdateSeries,
+}: AdminSeriesListItemProps) => {
return (
{
{series.description || 'No description available'}
-
+ handleUpdateSeries(series)}
+ className={'bg-green-200 rounded-2xl cursor-pointer px-4'}
+ >
시리즈 수정
From cf848ad56e3a03753842155ccdbcde7d46a4a9e0 Mon Sep 17 00:00:00 2001
From: JeongwooSeo <98446924+ShipFriend0516@users.noreply.github.com>
Date: Fri, 27 Jun 2025 16:45:58 +0900
Subject: [PATCH 4/9] =?UTF-8?q?feat:=20=EC=88=98=EC=A0=95=20=EC=84=B1?=
=?UTF-8?q?=EA=B3=B5=EC=8B=9C=20=ED=86=A0=EC=8A=A4=ED=8A=B8=EB=A9=94?=
=?UTF-8?q?=EC=8B=9C=EC=A7=80?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../series/CreateSeriesOverlayContainer.tsx | 23 +++++++++++++------
1 file changed, 16 insertions(+), 7 deletions(-)
diff --git a/app/entities/series/CreateSeriesOverlayContainer.tsx b/app/entities/series/CreateSeriesOverlayContainer.tsx
index f7331a9..0d0848c 100644
--- a/app/entities/series/CreateSeriesOverlayContainer.tsx
+++ b/app/entities/series/CreateSeriesOverlayContainer.tsx
@@ -14,10 +14,16 @@ const CreateSeriesOverlayContainer = ({
series,
handleCloseOverlay,
}: CreateSeriesOverlayContainerProps) => {
- const [seriesTitle, setSeriesTitle] = useState('');
- const [seriesDescription, setSeriesDescription] = useState('');
- const [seriesThumbnail, setSeriesThumbnail] = useState('');
const isEditMode = !!series;
+ const [seriesTitle, setSeriesTitle] = useState(
+ isEditMode ? series?.title || '' : ''
+ );
+ const [seriesDescription, setSeriesDescription] = useState(
+ isEditMode ? series?.description : ''
+ );
+ const [seriesThumbnail, setSeriesThumbnail] = useState(
+ isEditMode ? series?.thumbnailImage || '' : ''
+ );
const toast = useToast();
const postSeries = async () => {
@@ -43,11 +49,14 @@ const CreateSeriesOverlayContainer = ({
const editSeries = async () => {
try {
if (isEditMode) {
- await updateSeries(series.slug, {
+ const result = await updateSeries(series.slug, {
title: seriesTitle,
description: seriesDescription,
thumbnailImage: seriesThumbnail,
});
+ if (result._id) {
+ toast.success('시리즈가 성공적으로 수정되었습니다.');
+ }
}
} catch (e) {
toast.error('시리즈 수정 중 오류가 발생했습니다.');
@@ -80,7 +89,7 @@ const CreateSeriesOverlayContainer = ({
placeholder="시리즈의 이름"
className="w-full p-2.5 border border-gray-300 rounded-md focus:ring-2 focus:ring-emerald-500 focus:border-emerald-500 outline-none transition text-black"
onChange={(e) => setSeriesTitle(e.target.value)}
- value={isEditMode ? series?.title : seriesTitle || ''}
+ value={seriesTitle || ''}
/>
@@ -92,7 +101,7 @@ const CreateSeriesOverlayContainer = ({
placeholder="시리즈의 설명"
className="w-full p-2.5 border border-gray-300 rounded-md focus:ring-2 focus:ring-emerald-500 focus:border-emerald-500 outline-none transition text-black min-h-[100px] resize-y"
onChange={(e) => setSeriesDescription(e.target.value)}
- value={isEditMode ? series?.description : seriesDescription || ''}
+ value={seriesDescription || ''}
/>
@@ -105,7 +114,7 @@ const CreateSeriesOverlayContainer = ({
placeholder="시리즈의 썸네일 링크"
className="w-full p-2.5 border border-gray-300 rounded-md focus:ring-2 focus:ring-emerald-500 focus:border-emerald-500 outline-none transition text-black"
onChange={(e) => setSeriesThumbnail(e.target.value)}
- value={isEditMode ? series?.thumbnailImage : seriesThumbnail || ''}
+ value={seriesThumbnail || ''}
/>
From 49e3e9ac98204f8aaaa835e686ee7c2b100f38f6 Mon Sep 17 00:00:00 2001
From: JeongwooSeo <98446924+ShipFriend0516@users.noreply.github.com>
Date: Fri, 27 Jun 2025 16:46:33 +0900
Subject: [PATCH 5/9] =?UTF-8?q?style:=20list=20=EC=8A=A4=ED=83=80=EC=9D=BC?=
=?UTF-8?q?=20=EC=97=AC=EB=B0=B1=EB=84=93=EA=B2=8C?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/entities/series/list/AdminSeriesListItem.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/entities/series/list/AdminSeriesListItem.tsx b/app/entities/series/list/AdminSeriesListItem.tsx
index 112340f..5aab521 100644
--- a/app/entities/series/list/AdminSeriesListItem.tsx
+++ b/app/entities/series/list/AdminSeriesListItem.tsx
@@ -34,7 +34,7 @@ const AdminSeriesListItem = ({
)}
-
+
{series.title}
From ffc54309562f687cb3d7e37771eb12db33897207 Mon Sep 17 00:00:00 2001
From: JeongwooSeo <98446924+ShipFriend0516@users.noreply.github.com>
Date: Fri, 27 Jun 2025 17:00:49 +0900
Subject: [PATCH 6/9] =?UTF-8?q?fix:=20cache=2030=EC=B4=88=EB=A1=9C=20?=
=?UTF-8?q?=EA=B0=90=EC=86=8C?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/api/series/route.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/api/series/route.ts b/app/api/series/route.ts
index a771374..9bf9cd6 100644
--- a/app/api/series/route.ts
+++ b/app/api/series/route.ts
@@ -54,7 +54,7 @@ export async function GET(request: Request) {
return NextResponse.json(series, {
status: 200,
headers: {
- 'Cache-Control': 'public, max-age=60, s-maxage=60',
+ 'Cache-Control': 'public, max-age=30, s-maxage=30',
},
});
} catch (error: any) {
From 878a46cb0a6e061b9942b320271eb87d17947164 Mon Sep 17 00:00:00 2001
From: JeongwooSeo <98446924+ShipFriend0516@users.noreply.github.com>
Date: Fri, 27 Jun 2025 17:04:30 +0900
Subject: [PATCH 7/9] =?UTF-8?q?feat:=20=EC=8B=9C=EB=A6=AC=EC=A6=88=20?=
=?UTF-8?q?=EC=88=98=EC=A0=95,=20=EC=82=AD=EC=A0=9C=20=EA=B8=B0=EB=8A=A5?=
=?UTF-8?q?=20=EA=B5=AC=ED=98=84?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/admin/series/page.tsx | 57 ++++++++++++++++---
app/entities/common/Modal/DeleteModal.tsx | 5 +-
app/entities/series/api/series.ts | 5 ++
app/entities/series/list/AdminSeriesList.tsx | 3 +
.../series/list/AdminSeriesListItem.tsx | 7 ++-
5 files changed, 68 insertions(+), 9 deletions(-)
diff --git a/app/admin/series/page.tsx b/app/admin/series/page.tsx
index 6705b4f..8210cfc 100644
--- a/app/admin/series/page.tsx
+++ b/app/admin/series/page.tsx
@@ -7,7 +7,10 @@ import { useState } from 'react';
import AdminSeriesList from '@/app/entities/series/list/AdminSeriesList';
import Overlay from '@/app/entities/common/Overlay/Overlay';
import CreateSeriesOverlayContainer from '@/app/entities/series/CreateSeriesOverlayContainer';
+import { deleteSeries } from '@/app/entities/series/api/series';
+import DeleteModal from '@/app/entities/common/Modal/DeleteModal';
const AdminSeriesPage = () => {
+ const [seriesList, setSeriesList] = useState
(null);
const getSeriesListConfig: useDataFetchConfig = {
url: '/api/series',
method: 'GET',
@@ -16,19 +19,49 @@ const AdminSeriesPage = () => {
compact: 'true',
},
},
+ onSuccess: (data: Series[]) => {
+ setSeriesList(data);
+ },
};
-
- const { data: seriesList, loading } =
- useDataFetch(getSeriesListConfig);
+ const { loading } = useDataFetch(getSeriesListConfig);
const [createSeriesOpen, setCreateSeriesOpen] = useState(false);
- const [toUpdateSeries, setToUpdateSeries] = useState(null);
+ const [showDeleteDialog, setShowDeleteDialog] = useState(false);
+ const [selectedSeries, setSelectedSeries] = useState(null);
const handleUpdateSeries = (series: Series) => {
setCreateSeriesOpen(true);
- setToUpdateSeries(series);
+ setSelectedSeries(series);
};
const handleCloseOverlay = () => {
setCreateSeriesOpen(false);
- setToUpdateSeries(null);
+ setSelectedSeries(null);
+ };
+
+ const handleDeleteSeries = async (slug: string) => {
+ if (!seriesList) return;
+ try {
+ const data = await deleteSeries(slug);
+ if (data.success) {
+ console.log('시리즈 삭제 성공:', data);
+ } else {
+ console.error('시리즈 삭제 실패:', data);
+ }
+ } catch (error) {
+ console.error('시리즈 삭제 중 오류 발생:', error);
+ }
+
+ const updatedSeriesList = seriesList.filter(
+ (series) => series.slug !== slug
+ );
+ setSeriesList(updatedSeriesList);
+ setShowDeleteDialog(false);
+ setSelectedSeries(null);
+ };
+
+ const handleDeleteClick = (slug: string) => {
+ setShowDeleteDialog(true);
+ setSelectedSeries(
+ seriesList?.find((series) => series.slug === slug) || null
+ );
};
return (
@@ -52,6 +85,7 @@ const AdminSeriesPage = () => {
@@ -63,9 +97,18 @@ const AdminSeriesPage = () => {
+ {showDeleteDialog && (
+ setShowDeleteDialog(false)}
+ onConfirm={() => handleDeleteSeries(selectedSeries?.slug || '')}
+ />
+ )}
);
};
diff --git a/app/entities/common/Modal/DeleteModal.tsx b/app/entities/common/Modal/DeleteModal.tsx
index fea3201..82e5913 100644
--- a/app/entities/common/Modal/DeleteModal.tsx
+++ b/app/entities/common/Modal/DeleteModal.tsx
@@ -1,13 +1,16 @@
const DeleteModal = (props: {
onCancel: () => void;
onConfirm: () => void;
+ message?: string;
}) => {
+ const defaultMessage =
+ '게시글을 삭제하시겠습니까? 이 작업은 되돌릴 수 없습니다. 게시글이 영구적으로 삭제됩니다.';
return (
게시글을 삭제하시겠습니까?
- 이 작업은 되돌릴 수 없습니다. 게시글이 영구적으로 삭제됩니다.
+ {props.message ? props.message : defaultMessage}
{
+ const response = await axios.delete(`/api/series/${slug}`);
+ return response.data;
+};
diff --git a/app/entities/series/list/AdminSeriesList.tsx b/app/entities/series/list/AdminSeriesList.tsx
index 134e3cd..4cdd705 100644
--- a/app/entities/series/list/AdminSeriesList.tsx
+++ b/app/entities/series/list/AdminSeriesList.tsx
@@ -6,11 +6,13 @@ interface AdminSeriesListProps {
seriesList: Series[] | null | undefined;
loading: boolean;
handleUpdateSeries: (series: Series) => void;
+ handleDeleteClick: (slug: string) => void;
}
const AdminSeriesList = ({
loading,
seriesList,
handleUpdateSeries,
+ handleDeleteClick,
}: AdminSeriesListProps) => {
if (loading) {
return 로딩 중...
;
@@ -26,6 +28,7 @@ const AdminSeriesList = ({
key={index}
series={series}
handleUpdateSeries={handleUpdateSeries}
+ handleDeleteClick={handleDeleteClick}
/>
))}
diff --git a/app/entities/series/list/AdminSeriesListItem.tsx b/app/entities/series/list/AdminSeriesListItem.tsx
index 5aab521..2f57ac1 100644
--- a/app/entities/series/list/AdminSeriesListItem.tsx
+++ b/app/entities/series/list/AdminSeriesListItem.tsx
@@ -6,11 +6,13 @@ import React from 'react';
interface AdminSeriesListItemProps {
series: Series;
handleUpdateSeries: (series: Series) => void;
+ handleDeleteClick: (slug: string) => void;
}
const AdminSeriesListItem = ({
series,
handleUpdateSeries,
+ handleDeleteClick,
}: AdminSeriesListItemProps) => {
return (
-
시리즈 수정
-
+ handleDeleteClick(series.slug)}
+ className={'bg-red-200 rounded-2xl cursor-pointer px-4'}
+ >
시리즈 삭제
From 7ded2ac8ea5cc2e458bcf0eaa378cf9799622c2f Mon Sep 17 00:00:00 2001
From: JeongwooSeo <98446924+ShipFriend0516@users.noreply.github.com>
Date: Fri, 27 Jun 2025 17:07:09 +0900
Subject: [PATCH 8/9] =?UTF-8?q?fix:=20=EC=8B=9C=EB=A6=AC=EC=A6=88=20?=
=?UTF-8?q?=EA=B4=80=EB=A0=A8=20API=20=EC=9D=B8=EC=A6=9D=EC=9D=B4=20?=
=?UTF-8?q?=ED=95=84=EC=9A=94=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=88=98?=
=?UTF-8?q?=EC=A0=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/api/series/[slug]/route.ts | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/app/api/series/[slug]/route.ts b/app/api/series/[slug]/route.ts
index 79e3530..420453c 100644
--- a/app/api/series/[slug]/route.ts
+++ b/app/api/series/[slug]/route.ts
@@ -2,6 +2,7 @@ import { NextResponse } from 'next/server';
import dbConnect from '@/app/lib/dbConnect';
import Series from '@/app/models/Series';
import '@/app/models/Post';
+import { getServerSession } from 'next-auth';
export async function GET(
request: Request,
@@ -41,6 +42,12 @@ export async function PUT(
{ params }: { params: { slug: string } }
) {
try {
+ const session = await getServerSession();
+
+ if (!session) {
+ return new Response('Unauthorized', { status: 401 });
+ }
+
await dbConnect();
const body = await request.json();
@@ -77,6 +84,12 @@ export async function DELETE(
{ params }: { params: { slug: string } }
) {
try {
+ const session = await getServerSession();
+
+ if (!session) {
+ return new Response('Unauthorized', { status: 401 });
+ }
+
await dbConnect();
const deletedSeries = await Series.findOneAndDelete({ slug: params.slug });
From 664de05036594c43a71ad874ce1c33d82d198c5f Mon Sep 17 00:00:00 2001
From: JeongwooSeo <98446924+ShipFriend0516@users.noreply.github.com>
Date: Fri, 27 Jun 2025 17:07:24 +0900
Subject: [PATCH 9/9] =?UTF-8?q?feat:=20=EC=8B=9C=EB=A6=AC=EC=A6=88=20?=
=?UTF-8?q?=EC=82=AD=EC=A0=9C=20=EA=B8=B0=EB=8A=A5=20=EB=B9=84=ED=99=9C?=
=?UTF-8?q?=EC=84=B1=ED=99=94?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/entities/series/list/AdminSeriesListItem.tsx | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/app/entities/series/list/AdminSeriesListItem.tsx b/app/entities/series/list/AdminSeriesListItem.tsx
index 2f57ac1..33860bc 100644
--- a/app/entities/series/list/AdminSeriesListItem.tsx
+++ b/app/entities/series/list/AdminSeriesListItem.tsx
@@ -64,7 +64,10 @@ const AdminSeriesListItem = ({
handleDeleteClick(series.slug)}
- className={'bg-red-200 rounded-2xl cursor-pointer px-4'}
+ disabled={true}
+ className={
+ 'disabled:bg-neutral-200 disabled:cursor-not-allowed bg-red-200 rounded-2xl cursor-pointer px-4'
+ }
>
시리즈 삭제