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
194 changes: 107 additions & 87 deletions src/app/(layout)/archive/_components/ArchiveCardGrid/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,72 +4,76 @@ import { useState, useEffect } from 'react';
import Card from '@/components/ui/Card';
import { useModalStore } from '@/stores/useModalStore';
import { TagType } from '@/types';
import { useTemplatesLikes } from '@/hooks/template/useTemplateLikes';
import { useRecentlyUsedTemplates } from '@/hooks/template/useRecentlyUsedTemplates';
import { useFolderDetail } from '@/hooks/folder/useFolderDetail';
import { Template } from '@/services/template/getTemplates';

interface ArchiveCardGridProps {
selectedFolderId: string;
selectedTag?: TagType;
sortType: 'popular' | 'latest';
}

// ν…œν”Œλ¦Ώ 데이터 νƒ€μž… μ •μ˜
interface TemplateData {
id: string;
templateId: number;
title: string;
description: string;
tags: string[];
likes: number;
content: string;
folderId: string;
}

// 폴더별 더미 데이터
const folderData: Record<string, TemplateData[]> = {
'1': Array.from({ length: 32 }, (_, index) => ({
id: `fav_${index + 1}`,
templateId: index + 1,
title: `μ°œν•œ ν…œν”Œλ¦Ώ ${index + 1}`,
description:
'μ°œν•œ ν…œν”Œλ¦Ώμž…λ‹ˆλ‹€. κΈ€λ‘œμš°μ—… κΈ€μ“°κΈ° μ„œλΉ„μŠ€λŠ” μ—¬λŸ¬ μƒν™©μ—μ„œ μ‚¬μš©μžμ˜ κΈ€μ“°κΈ° κ²½ν—˜μ„ λ•κ³ μž ν•©λ‹ˆλ‹€.',
tags: ['인사말', 'μžκΈ°μ†Œκ°œ'],
likes: 150 + index,
content: `μ°œν•œ ν…œν”Œλ¦Ώ ${index + 1}의 λ‚΄μš©μž…λ‹ˆλ‹€.\n\nμ•ˆλ…•ν•˜μ„Έμš” 잘 λΆ€νƒλ“œλ¦½λ‹ˆλ‹€.`,
folderId: '1',
})),
'2': Array.from({ length: 5 }, (_, index) => ({
id: `recent_${index + 1}`,
templateId: 100 + index + 1,
title: `졜근 μ‚¬μš©ν•œ ν…œν”Œλ¦Ώ ${index + 1}`,
description:
'μ΅œκ·Όμ— μ‚¬μš©ν•œ ν…œν”Œλ¦Ώμž…λ‹ˆλ‹€. κΈ€λ‘œμš°μ—… κΈ€μ“°κΈ° μ„œλΉ„μŠ€λŠ” μ—¬λŸ¬ μƒν™©μ—μ„œ μ‚¬μš©μžμ˜ κΈ€μ“°κΈ° κ²½ν—˜μ„ λ•κ³ μž ν•©λ‹ˆλ‹€.',
tags: ['감사글', '곡지글'],
likes: 80 + index,
content: `졜근 μ‚¬μš©ν•œ ν…œν”Œλ¦Ώ ${index + 1}의 λ‚΄μš©μž…λ‹ˆλ‹€.\n\nκ°μ‚¬ν•©λ‹ˆλ‹€.`,
folderId: '2',
})),
'3': Array.from({ length: 8 }, (_, index) => ({
id: `user1_${index + 1}`,
templateId: 200 + index + 1,
title: `μ‚¬μš©μž 폴더1 ν…œν”Œλ¦Ώ ${index + 1}`,
description:
'μ‚¬μš©μžκ°€ λ§Œλ“  ν΄λ”μ˜ ν…œν”Œλ¦Ώμž…λ‹ˆλ‹€. κΈ€λ‘œμš°μ—… κΈ€μ“°κΈ° μ„œλΉ„μŠ€λŠ” μ—¬λŸ¬ μƒν™©μ—μ„œ μ‚¬μš©μžμ˜ κΈ€μ“°κΈ° κ²½ν—˜μ„ λ•κ³ μž ν•©λ‹ˆλ‹€.',
tags: ['뢀탁글', 'μ œμ•ˆκΈ€'],
likes: 60 + index,
content: `μ‚¬μš©μž 폴더1 ν…œν”Œλ¦Ώ ${index + 1}의 λ‚΄μš©μž…λ‹ˆλ‹€.\n\n잘 λΆ€νƒλ“œλ¦½λ‹ˆλ‹€.`,
folderId: '3',
})),
'4': Array.from({ length: 3 }, (_, index) => ({
id: `user2_${index + 1}`,
templateId: 300 + index + 1,
title: `μ‚¬μš©μž 폴더2 ν…œν”Œλ¦Ώ ${index + 1}`,
description:
'μ‚¬μš©μžκ°€ λ§Œλ“  ν΄λ”μ˜ ν…œν”Œλ¦Ώμž…λ‹ˆλ‹€. κΈ€λ‘œμš°μ—… κΈ€μ“°κΈ° μ„œλΉ„μŠ€λŠ” μ—¬λŸ¬ μƒν™©μ—μ„œ μ‚¬μš©μžμ˜ κΈ€μ“°κΈ° κ²½ν—˜μ„ λ•κ³ μž ν•©λ‹ˆλ‹€.',
tags: ['ν›„κΈ°μž‘μ„±', 'μ†Œμ…œκΈ€'],
likes: 40 + index,
content: `μ‚¬μš©μž 폴더2 ν…œν”Œλ¦Ώ ${index + 1}의 λ‚΄μš©μž…λ‹ˆλ‹€.\n\nκ°μ‚¬ν•©λ‹ˆλ‹€.`,
folderId: '4',
})),
};
// ν…œν”Œλ¦Ώ 데이터 νƒ€μž… μ •μ˜ (ν˜„μž¬ μ‚¬μš©λ˜μ§€ μ•ŠμŒ - API νƒ€μž…μœΌλ‘œ λŒ€μ²΄λ¨)
// interface TemplateData {
// id: string;
// templateId: number;
// title: string;
// description: string;
// tags: string[];
// likes: number;
// content: string;
// folderId: string;
// }

// 폴더별 더미 데이터 (ν˜„μž¬ μ‚¬μš©λ˜μ§€ μ•ŠμŒ - API μ—°λ™μœΌλ‘œ λŒ€μ²΄λ¨)
// const folderData: Record<string, TemplateData[]> = {
// '1': Array.from({ length: 32 }, (_, index) => ({
// id: `fav_${index + 1}`,
// templateId: index + 1,
// title: `μ°œν•œ ν…œν”Œλ¦Ώ ${index + 1}`,
// description:
// 'μ°œν•œ ν…œν”Œλ¦Ώμž…λ‹ˆλ‹€. κΈ€λ‘œμš°μ—… κΈ€μ“°κΈ° μ„œλΉ„μŠ€λŠ” μ—¬λŸ¬ μƒν™©μ—μ„œ μ‚¬μš©μžμ˜ κΈ€μ“°κΈ° κ²½ν—˜μ„ λ•κ³ μž ν•©λ‹ˆλ‹€.',
// tags: ['인사말', 'μžκΈ°μ†Œκ°œ'],
// likes: 150 + index,
// content: `μ°œν•œ ν…œν”Œλ¦Ώ ${index + 1}의 λ‚΄μš©μž…λ‹ˆλ‹€.\n\nμ•ˆλ…•ν•˜μ„Έμš” 잘 λΆ€νƒλ“œλ¦½λ‹ˆλ‹€.`,
// folderId: '1',
// })),
// '2': Array.from({ length: 5 }, (_, index) => ({
// id: `recent_${index + 1}`,
// templateId: 100 + index + 1,
// title: `졜근 μ‚¬μš©ν•œ ν…œν”Œλ¦Ώ ${index + 1}`,
// description:
// 'μ΅œκ·Όμ— μ‚¬μš©ν•œ ν…œν”Œλ¦Ώμž…λ‹ˆλ‹€. κΈ€λ‘œμš°μ—… κΈ€μ“°κΈ° μ„œλΉ„μŠ€λŠ” μ—¬λŸ¬ μƒν™©μ—μ„œ μ‚¬μš©μžμ˜ κΈ€μ“°κΈ° κ²½ν—˜μ„ λ•κ³ μž ν•©λ‹ˆλ‹€.',
// tags: ['감사글', '곡지글'],
// likes: 80 + index,
// content: `졜근 μ‚¬μš©ν•œ ν…œν”Œλ¦Ώ ${index + 1}의 λ‚΄μš©μž…λ‹ˆλ‹€.\n\nκ°μ‚¬ν•©λ‹ˆλ‹€.`,
// folderId: '2',
// })),
// '3': Array.from({ length: 8 }, (_, index) => ({
// id: `user1_${index + 1}`,
// templateId: 200 + index + 1,
// title: `μ‚¬μš©μž 폴더1 ν…œν”Œλ¦Ώ ${index + 1}`,
// description:
// 'μ‚¬μš©μžκ°€ λ§Œλ“  ν΄λ”μ˜ ν…œν”Œλ¦Ώμž…λ‹ˆλ‹€. κΈ€λ‘œμš°μ—… κΈ€μ“°κΈ° μ„œλΉ„μŠ€λŠ” μ—¬λŸ¬ μƒν™©μ—μ„œ μ‚¬μš©μžμ˜ κΈ€μ“°κΈ° κ²½ν—˜μ„ λ•κ³ μž ν•©λ‹ˆλ‹€.',
// tags: ['뢀탁글', 'μ œμ•ˆκΈ€'],
// likes: 60 + index,
// content: `μ‚¬μš©μž 폴더1 ν…œν”Œλ¦Ώ ${index + 1}의 λ‚΄μš©μž…λ‹ˆλ‹€.\n\n잘 λΆ€νƒλ“œλ¦½λ‹ˆλ‹€.`,
// folderId: '3',
// })),
// '4': Array.from({ length: 3 }, (_, index) => ({
// id: `user2_${index + 1}`,
// templateId: 300 + index + 1,
// title: `μ‚¬μš©μž 폴더2 ν…œν”Œλ¦Ώ ${index + 1}`,
// description:
// 'μ‚¬μš©μžκ°€ λ§Œλ“  ν΄λ”μ˜ ν…œν”Œλ¦Ώμž…λ‹ˆλ‹€. κΈ€λ‘œμš°μ—… κΈ€μ“°κΈ° μ„œλΉ„μŠ€λŠ” μ—¬λŸ¬ μƒν™©μ—μ„œ μ‚¬μš©μžμ˜ κΈ€μ“°κΈ° κ²½ν—˜μ„ λ•κ³ μž ν•©λ‹ˆλ‹€.',
// tags: ['ν›„κΈ°μž‘μ„±', 'μ†Œμ…œκΈ€'],
// likes: 40 + index,
// content: `μ‚¬μš©μž 폴더2 ν…œν”Œλ¦Ώ ${index + 1}의 λ‚΄μš©μž…λ‹ˆλ‹€.\n\nκ°μ‚¬ν•©λ‹ˆλ‹€.`,
// folderId: '4',
// })),
// };

export default function ArchiveCardGrid({
selectedFolderId,
Expand All @@ -80,6 +84,46 @@ export default function ArchiveCardGrid({
const [isLoading, setIsLoading] = useState(false);
const { openModal, currentModal } = useModalStore();

// 폴더별 데이터 API 연동
const isLikes = selectedFolderId === '1';
const isRecent = selectedFolderId === '2';
const folderIdNum = Number(selectedFolderId);

const { data: likesData } = useTemplatesLikes();
const { data: recentData } = useRecentlyUsedTemplates();
const { data: folderDetailData } = useFolderDetail(
!isLikes && !isRecent && !isNaN(folderIdNum) ? folderIdNum : 0,
);

// ν…œν”Œλ¦Ώ 데이터 μΆ”μΆœ
let templates: Template[] = [];
if (isLikes) {
templates = likesData?.templates ?? [];
} else if (isRecent) {
templates = recentData?.templates ?? [];
} else if (folderDetailData) {
templates = folderDetailData.templates ?? [];
}

// νƒœκ·Έ 필터링
let filteredTemplates: Template[] = templates;
if (selectedTag) {
filteredTemplates = templates.filter((card) =>
card.tags.some((tag: string) => tag === selectedTag),
);
}

// μ •λ ¬
if (sortType === 'popular') {
filteredTemplates = [...filteredTemplates].sort((a, b) => b.likeCount - a.likeCount);
} else {
filteredTemplates = [...filteredTemplates].sort((a, b) => b.templateId - a.templateId);
}

// νŽ˜μ΄μ§•
const displayedCards = filteredTemplates.slice(0, visibleCards);
const hasMoreCards = visibleCards < filteredTemplates.length;

// μ»΄ν¬λ„ŒνŠΈ 마운트 μ‹œμ™€ λͺ¨λ‹¬μ΄ λ‹«νž λ•Œλ§Œ μΉ΄λ“œ 클릭 μƒνƒœ μ΄ˆκΈ°ν™”
useEffect(() => {
// λͺ¨λ‹¬μ΄ λ‹«νž λ•Œλ§Œ μΉ΄λ“œ 클릭 μƒνƒœλ₯Ό μ΄ˆκΈ°ν™”
Expand All @@ -93,26 +137,6 @@ export default function ArchiveCardGrid({
setVisibleCards(15);
}, [selectedFolderId]);

// ν˜„μž¬ ν΄λ”μ˜ 데이터 κ°€μ Έμ˜€κΈ°
const getCurrentFolderData = () => {
const data = folderData[selectedFolderId] || [];

// νƒœκ·Έ 필터링
let filteredData = data;
if (selectedTag) {
filteredData = data.filter((card) => card.tags.some((tag: string) => tag === selectedTag));
}

// μ •λ ¬
if (sortType === 'popular') {
filteredData.sort((a, b) => b.likes - a.likes);
} else {
filteredData.sort((a, b) => b.templateId - a.templateId); // μ΅œμ‹ μˆœ (ID κΈ°μ€€)
}

return filteredData;
};

const handleLoadMore = () => {
setIsLoading(true);
// 더 뢈러였기 둜직 (μΆ”ν›„ API μ—°κ²°)
Expand All @@ -123,7 +147,7 @@ export default function ArchiveCardGrid({
};

// λͺ¨λ‹¬ μ—΄κΈ° ν•Έλ“€λŸ¬ - μΉ΄λ“œ 클릭 μ‹œ λͺ¨λ‹¬ 연결을 μœ„ν•œ μƒνƒœ 처리
const handleCardClick = (templateId: number, cardData: TemplateData) => {
const handleCardClick = (templateId: number, cardData: Template) => {
console.log('μΉ΄λ“œ 클릭:', {
templateId,
folderId: selectedFolderId,
Expand All @@ -138,22 +162,18 @@ export default function ArchiveCardGrid({
});
};

const currentData = getCurrentFolderData();
const displayedCards = currentData.slice(0, visibleCards);
const hasMoreCards = visibleCards < currentData.length;

return (
<div>
{/* μΉ΄λ“œ κ·Έλ¦¬λ“œ - 3μ—΄λ‘œ 배치 */}
<div className="grid grid-cols-3 gap-x-[13.33px] gap-y-[12px]">
{displayedCards.map((card) => (
<Card
key={card.id}
key={card.templateId}
variant="large"
title={card.title}
description={card.description}
description={card.content}
tags={card.tags}
likes={card.likes}
likes={card.likeCount}
onClick={() => handleCardClick(card.templateId, card)}
className="cursor-pointer transition-all duration-200 hover:scale-[1.02] hover:shadow-lg"
/>
Expand Down
84 changes: 47 additions & 37 deletions src/app/(layout)/archive/_components/ArchiveSidebar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import { useRouter } from 'next/navigation';
import ArchiveFolderStatus from '../ArchiveFolderStatus';
import ArchiveFolderInput from '../ArchiveFolderInput';
import ArchiveModalWarning from '../ArchiveModalWarning';
import { useFolders } from '@/hooks/folder/useFolders';
import { useCreateFolder } from '@/hooks/folder/useCreateFolder';
import { useDeleteFolder } from '@/hooks/folder/useDeleteFolder';

interface ArchiveSidebarProps {
selectedFolderId: string;
Expand All @@ -15,19 +18,27 @@ export default function ArchiveSidebar({ selectedFolderId, onFolderSelect }: Arc
const router = useRouter();
const [isCreatingFolder, setIsCreatingFolder] = useState(false);
const [deleteModalOpen, setDeleteModalOpen] = useState(false);
const [folderToDelete, setFolderToDelete] = useState<string | null>(null);

// ν…ŒμŠ€νŠΈμš© 더미 데이터
const [folders, setFolders] = useState([
{ id: '1', name: 'μ°œν•œ ν…œν”Œλ¦Ώ', templateCount: 32 },
{ id: '2', name: '졜근 μ‚¬μš©ν•œ ν…œν”Œλ¦Ώ', templateCount: 5 },
{ id: '3', name: 'μ‚¬μš©μž 폴더1', templateCount: 8 },
{ id: '4', name: 'μ‚¬μš©μž 폴더2', templateCount: 3 },
]);

const handleFolderClick = (folderId: string) => {
onFolderSelect(folderId);
console.log('폴더 선택:', folderId);
const [folderToDelete, setFolderToDelete] = useState<number | null>(null);

// 폴더 λͺ©λ‘ API 연동
const { data: foldersData } = useFolders();
const createFolderMutation = useCreateFolder();
const deleteFolderMutation = useDeleteFolder();

// μ°œν•œ ν…œν”Œλ¦Ώ, 졜근 μ‚¬μš©ν•œ ν…œν”Œλ¦Ώμ€ κ³ μ •
const fixedFolders = [
{ id: 1, name: 'μ°œν•œ ν…œν”Œλ¦Ώ' },
{ id: 2, name: '졜근 μ‚¬μš©ν•œ ν…œν”Œλ¦Ώ' },
];

// 폴더 λͺ©λ‘ ν•©μΉ˜κΈ°
const folders = [
...fixedFolders,
...(foldersData?.folders?.map((f) => ({ id: f.folderId, name: f.name })) || []),
];

const handleFolderClick = (folderId: number) => {
onFolderSelect(folderId.toString());
};

const handleFolderDoubleClick = (folderId: string) => {
Expand All @@ -39,39 +50,37 @@ export default function ArchiveSidebar({ selectedFolderId, onFolderSelect }: Arc
};

const handleFolderSave = (folderName: string) => {
console.log('폴더 μ €μž₯:', folderName);
// μƒˆ 폴더λ₯Ό λͺ©λ‘μ— μΆ”κ°€
const newFolder = {
id: Date.now().toString(),
name: folderName,
templateCount: 0,
};
setFolders((prev) => [...prev, newFolder]);
setIsCreatingFolder(false);
createFolderMutation.mutate(
{ name: folderName },
{
onSuccess: () => setIsCreatingFolder(false),
},
);
};

const handleFolderCancel = () => {
console.log('폴더 생성 μ·¨μ†Œ');
setIsCreatingFolder(false);
};

const handleExploreClick = () => {
router.push('/explore');
};

const handleDeleteClick = (folderId: string) => {
const handleDeleteClick = (folderId: number) => {
setFolderToDelete(folderId);
setDeleteModalOpen(true);
};

const handleDeleteConfirm = () => {
if (folderToDelete) {
setFolders((prev) => prev.filter((folder) => folder.id !== folderToDelete));
console.log('폴더 μ‚­μ œ:', folderToDelete);
// μ‚­μ œλœ 폴더가 ν˜„μž¬ μ„ νƒλœ 폴더라면 κΈ°λ³Έ ν΄λ”λ‘œ λ³€κ²½
if (selectedFolderId === folderToDelete) {
onFolderSelect('1'); // μ°œν•œ ν…œν”Œλ¦ΏμœΌλ‘œ λ³€κ²½
}
deleteFolderMutation.mutate(folderToDelete, {
onSuccess: () => {
// μ‚­μ œλœ 폴더가 ν˜„μž¬ μ„ νƒλœ 폴더라면 κΈ°λ³Έ ν΄λ”λ‘œ λ³€κ²½
if (selectedFolderId === folderToDelete.toString()) {
onFolderSelect('1');
}
},
});
}
setDeleteModalOpen(false);
setFolderToDelete(null);
Expand All @@ -88,17 +97,17 @@ export default function ArchiveSidebar({ selectedFolderId, onFolderSelect }: Arc
style={{ width: '312px', height: '640px' }}
>
<div className="flex-1">
{/* κΈ°μ‘΄ 폴더듀 */}
{/* 폴더 λͺ©λ‘ */}
{folders.map((folder) => (
<ArchiveFolderStatus
key={folder.id}
folderId={folder.id}
folderId={folder.id.toString()}
folderName={folder.name}
isSelected={selectedFolderId === folder.id}
isDeletable={folder.id !== '1' && folder.id !== '2'} // μ°œν•œ ν…œν”Œλ¦Ώ, 졜근 μ‚¬μš©ν•œ ν…œν”Œλ¦Ώ μ œμ™Έ
onClick={handleFolderClick}
onDoubleClick={handleFolderDoubleClick}
onDelete={handleDeleteClick}
isSelected={selectedFolderId === folder.id.toString()}
isDeletable={folder.id !== 1 && folder.id !== 2}
onClick={() => handleFolderClick(folder.id)}
onDoubleClick={() => handleFolderDoubleClick(folder.id.toString())}
onDelete={() => handleDeleteClick(folder.id)}
/>
))}

Expand All @@ -117,6 +126,7 @@ export default function ArchiveSidebar({ selectedFolderId, onFolderSelect }: Arc
<button
className="button-md text-layout-grey4 hover:text-layout-grey6 hover:bg-layout-grey3 w-full rounded-lg px-4 py-3 text-left transition-all duration-200"
onClick={handleCreateFolderClick}
disabled={createFolderMutation.isPending}
>
+ 폴더 λ§Œλ“€κΈ°
</button>
Expand Down
Loading