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
74 changes: 2 additions & 72 deletions src/app/(layout)/archive/_components/ArchiveCardGrid/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,74 +15,14 @@ interface ArchiveCardGridProps {
sortType: 'popular' | 'latest';
}

// 템플릿 데이터 타입 정의 (현재 사용되지 않음 - 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,
selectedTag,
sortType,
}: ArchiveCardGridProps) {
const [visibleCards, setVisibleCards] = useState(15);
const [isLoading, setIsLoading] = useState(false);
const { openModal, currentModal } = useModalStore();
const { openModal } = useModalStore();

// 폴더별 데이터 API 연동
const isLikes = selectedFolderId === '1';
Expand Down Expand Up @@ -124,29 +64,20 @@ export default function ArchiveCardGrid({
const displayedCards = filteredTemplates.slice(0, visibleCards);
const hasMoreCards = visibleCards < filteredTemplates.length;

// 컴포넌트 마운트 시와 모달이 닫힐 때만 카드 클릭 상태 초기화
useEffect(() => {
// 모달이 닫힐 때만 카드 클릭 상태를 초기화
if (currentModal === null) {
// clearAllCards(); // useCardStore가 없으므로 주석 처리
}
}, [currentModal]);

// 폴더가 변경될 때 visibleCards 초기화
useEffect(() => {
setVisibleCards(15);
}, [selectedFolderId]);

const handleLoadMore = () => {
setIsLoading(true);
// 더 불러오기 로직 (추후 API 연결)
setTimeout(() => {
setVisibleCards((prev) => prev + 15);
setIsLoading(false);
}, 1000);
};

// 모달 열기 핸들러 - 카드 클릭 시 모달 연결을 위한 상태 처리
// 모달 열기 핸들러
const handleCardClick = (templateId: number, cardData: Template) => {
console.log('카드 클릭:', {
templateId,
Expand All @@ -156,7 +87,6 @@ export default function ArchiveCardGrid({
timestamp: new Date().toISOString(),
});

// 모달 열기 - 모달 스토어에서 지원하는 파라미터만 전달
openModal('view', {
templateId,
});
Expand Down
64 changes: 18 additions & 46 deletions src/components/ui/Card/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ interface CardProps {
likes: number;
onClick?: () => void;
className?: string;
isSelected?: boolean;
onSelectionChange?: (cardId: string) => void;
cardId?: string;
}

const Card: React.FC<CardProps> = ({
Expand All @@ -25,14 +28,15 @@ const Card: React.FC<CardProps> = ({
likes,
onClick,
className,
isSelected = false,
onSelectionChange,
cardId,
}) => {
const [isClicked, setIsClicked] = useState(false);
const [isHovered, setIsHovered] = useState(false);
const cardRef = useRef<HTMLDivElement>(null);
const descriptionRef = useRef<HTMLDivElement>(null);
const [truncatedDescription, setTruncatedDescription] = useState(description);

const state = isClicked ? 'click' : isHovered ? 'hover' : 'default';
const state = isSelected ? 'click' : isHovered ? 'hover' : 'default';

const sizeStyle: Record<variantType, string> = {
large: 'w-[320px] h-[204px]',
Expand Down Expand Up @@ -74,7 +78,7 @@ const Card: React.FC<CardProps> = ({
'w-[168px] h-[26px] overflow-hidden text-ellipsis whitespace-nowrap',
);

// 3줄 제한을 위한 커스텀 로직 추가
// 3줄 제한을 위한 커스텀 로직
useEffect(() => {
function truncateToThreeLines() {
const element = descriptionRef.current;
Expand Down Expand Up @@ -110,71 +114,39 @@ const Card: React.FC<CardProps> = ({
};
}, [description, variant, state]);

// 클릭 상태 유지
useEffect(() => {
if (isClicked) {
// 클릭 상태를 로컬 스토리지에 저장하여 페이지 새로고침 후에도 유지
const cardId = `${title}-${variant}`;
localStorage.setItem(`card-clicked-${cardId}`, 'true');
}
}, [isClicked, title, variant]);

// 컴포넌트 마운트 시 이전 클릭 상태 복원
useEffect(() => {
const cardId = `${title}-${variant}`;
const wasClicked = localStorage.getItem(`card-clicked-${cardId}`);
if (wasClicked === 'true') {
setIsClicked(true);
}
}, [title, variant]);

// 모달 닫힘 이벤트 감지
useEffect(() => {
// 모달 닫힘 이벤트 리스너 설정
const handleModalClose = () => {
const cardId = `${title}-${variant}`;
localStorage.removeItem(`card-clicked-${cardId}`);
setIsClicked(false);
};

// 사용자 정의 이벤트 생성 및 구독
window.addEventListener('modal-closed', handleModalClose);

// cleanup
return () => {
window.removeEventListener('modal-closed', handleModalClose);
};
}, [title, variant]);

const handleClick = () => {
if (!isClicked) {
setIsClicked(true);
// 선택 상태 변경 (cardId가 있고 onSelectionChange가 제공된 경우에만)
if (cardId && onSelectionChange) {
onSelectionChange(cardId);
}

// 기존 onClick 핸들러 호출
if (onClick) {
onClick();
}
};

return (
<div
ref={cardRef}
onMouseEnter={() => setIsHovered(true)}
onMouseLeave={() => setIsHovered(false)}
onClick={handleClick}
className={clsx(
'z-10 flex flex-col justify-between rounded-[8px] p-[16px] transition-all',
'z-10 flex flex-col justify-between rounded-[6px] p-[16px] transition-all',
sizeStyle[variant],
backgroundStyle[variant][state],
variant === 'small' && state === 'hover' ? 'z-30' : 'z-10',
isClicked ? 'clicked' : '', // 클릭 상태를 나타내는 CSS 클래스 추가
isSelected ? 'selected' : '', // 선택 상태를 나타내는 CSS 클래스
className,
)}
>
<div className="flex h-full flex-col justify-between">
<div className="flex flex-1 flex-col">
<div className="mb-[8px] flex flex-wrap gap-1">
{tags && tags.map((tag, idx) => <CardTag key={idx} text={tag} />)}
{tags &&
tags
.slice(0, variant === 'small' && state !== 'hover' ? 2 : tags.length)
.map((tag, idx) => <CardTag key={idx} text={tag} />)}
</div>
<div className={titleStyle}>{title}</div>
<div
Expand Down
2 changes: 1 addition & 1 deletion src/components/ui/CardTag/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ interface CardTagProps {

const CardTag: React.FC<CardTagProps> = ({ text }) => {
return (
<div className="bg-primary-navy4 flex h-[24px] w-[80px] items-center justify-center rounded-full text-sm text-white">
<div className="bg-primary-navy4 flex h-[24px] w-[80px] items-center justify-center rounded-[5px] text-sm text-white">
{text}
</div>
);
Expand Down
3 changes: 0 additions & 3 deletions src/components/ui/TagSearchButton/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,7 @@ export const TagSearchButton: React.FC<TagSearchButtonProps> = ({
loadIcon();
}, [id, code, selected]);

console.log('TagSearchButton 렌더링:', tag, '선택됨:', selected);

const handleClick = () => {
console.log('TagSearchButton 클릭:', tag, '현재 선택 상태:', selected);
if (onClick) {
onClick();
}
Expand Down