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
63 changes: 42 additions & 21 deletions src/components/IdolCard.jsx
Original file line number Diff line number Diff line change
@@ -1,40 +1,61 @@
import React, { useState } from 'react';
import React from 'react';
import checkIcon from '@/assets/images/check.png';

const IdolCard = ({ idol }) => {
const [isSelected, setIsSelected] = useState(false);
const IdolCard = ({
children,
idol,
isSelectable = true,
isSelected = false,
isDisabled = false,
sizeClass = 'w-[98px] h-[98px] tablet:w-[128px] tablet:h-[128px]',
onClick,
}) => {
const defaultImage = 'https://link24.kr/9iFIhh0';

console.log('IdolCard ๋ฐ›์€ ๋ฐ์ดํ„ฐ:', idol);

return (
<div className="bg-midnightBlack p-6 flex justify-center">
<div className="p-1 flex flex-col items-center relative">
<div
className="relative w-[98px] h-[98px] flex items-center justify-center rounded-full cursor-pointer transition-all"
onClick={() => setIsSelected(!isSelected)}
className={`relative ${sizeClass} p-[2px] flex items-center justify-center rounded-full
${isDisabled ? 'opacity-50 cursor-not-allowed' : isSelectable ? 'cursor-pointer' : 'cursor-default'} transition-all`} // ๋น„ํ™œ์„ฑํ™”๋œ ๊ฒฝ์šฐ ํˆฌ๋ช…๋„ 50%
onClick={
!isDisabled && isSelectable ? () => onClick(idol.id) : undefined
} // ๋น„ํ™œ์„ฑํ™”๋œ ๊ฒฝ์šฐ ํด๋ฆญ ๋ฐฉ์ง€
>
<div className="absolute inset-0 rounded-full border-[3px] border-red-400 transition-all"></div>
{children}
<div className="absolute inset-0 rounded-full border-[1.3px] border-coralRed z-10"></div>

<div className="absolute left-[5px] top-[5px] w-[88px] h-[88px] rounded-full overflow-hidden bg-white">
<div className="absolute inset-0 m-1.5 rounded-full overflow-hidden">
<img
src={idol?.profilePicture || defaultImage} // API์—์„œ ๋ฐ›์€ ์ด๋ฏธ์ง€ ์ ์šฉ
alt={idol?.name || 'Default Profile'}
className="absolute inset-0 w-full h-full object-cover transition-all"
src={idol.profilePicture || defaultImage}
alt={idol.name}
className="w-full h-full object-cover"
/>
</div>

{isSelected && (
<div className="absolute left-[5px] top-[5px] w-[88px] h-[88px] rounded-full bg-gradient-to-r from-red-400 to-pink-500 opacity-50 transition-all"></div>
{/* ๋น„ํ™œ์„ฑํ™”๋œ ๊ฒฝ์šฐ ํด๋ฆญ ์ฐจ๋‹จ & ๋งˆ์šฐ์Šค ๊ธˆ์ง€ ์ปค์„œ ์ ์šฉ */}
{isDisabled && (
<div
className="absolute inset-0 w-full h-full cursor-not-allowed"
style={{ cursor: 'not-allowed', pointerEvents: 'auto' }}
/>
)}

{isSelected && (
<img
src={checkIcon}
alt="check"
className="absolute w-[45.45%] h-[45.45%] top-[27.5%] left-[27.5%] transition-all"
/>
{isSelected && isSelectable && (
<>
<div className="absolute inset-0 rounded-full bg-gradient-to-r from-coralRed to-pinkPunch opacity-50 z-20" />
<img
src={checkIcon}
alt="check"
className="absolute w-[40%] h-[40%] top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 z-30"
/>
</>
)}
</div>

<div className="mt-1 text-center">
<p className="text-white text-mobile font-bold">{idol.name}</p>
<p className="text-white/70 text-xs">{idol.group || '๊ทธ๋ฃน ์—†์Œ'}</p>
</div>
</div>
);
};
Expand Down
48 changes: 0 additions & 48 deletions src/components/IdolImage.jsx

This file was deleted.

61 changes: 0 additions & 61 deletions src/pages/myPage/CheckedIdolCard.jsx

This file was deleted.

113 changes: 61 additions & 52 deletions src/pages/myPage/MyPage.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useState, useEffect } from 'react';
import Header from '@/components/Header';
import CheckedIdolCard from '@/pages/myPage/CheckedIdolCard';
import IdolCard from '@/components/IdolCard';
import nextIcon from '@/assets/icons/nextIcon.svg';
import prevIcon from '@/assets/icons/prevIcon.svg';
import { fetchIdols } from '@/apis/myPageApi.js';
Expand Down Expand Up @@ -100,7 +100,7 @@ const MyPage = () => {

return (
<div key={idol.id} className="relative cursor-default">
<CheckedIdolCard
<IdolCard
idol={idol}
isSelectable={false}
isDisabled={false}
Expand All @@ -111,82 +111,91 @@ const MyPage = () => {
className="absolute -top-0 -right-[0] w-7 h-7 z-50 flex items-center justify-center
bg-transparent transition-opacity cursor-pointer"
>
<img src={xButton} alt="Remove" className="w-full h-full" />
<img
src={xButton}
alt="Remove"
className="w-full h-full"
/>
</button>
</CheckedIdolCard>
</IdolCard>
</div>
);
})}
</div>
</div>

<div className="w-full max-w-[1200px] border-b border-gray-700 my-6"></div>

<h2 className="text-white text-[16px] tablet:text-[20px] pc:text-[24px] font-bold self-start mt-6">
๊ด€์‹ฌ ์žˆ๋Š” ์•„์ด๋Œ์„ ์ถ”๊ฐ€ํ•ด๋ณด์„ธ์š”.
</h2>
</div>

<div className="relative w-full max-w-[1200px] mt-[10px]">

<button
onClick={prevPage}
disabled={currentPage === 0}
<div className="relative w-full max-w-[1200px] mt-[10px]">
<button
onClick={prevPage}
disabled={currentPage === 0}
className="absolute left-[1%] tablet:left-[1.5%] pc:left-[-4.5%] top-1/2 transform -translate-y-1/2
bg-[rgba(27,27,27,0.8)] hover:bg-[rgba(27,27,27,1)] transition-all w-[29px] h-[135px]
rounded-[4px] flex items-center justify-center"
>
<img src={prevIcon}
alt="Previous"
className="w-[6px] h-[12px] object-contain"
/>
<img
src={prevIcon}
alt="Previous"
className="w-[6px] h-[12px] object-contain"
/>
</button>

{/* ์•„์ด๋Œ ๋ฆฌ์ŠคํŠธ */}
<div className="grid grid-cols-3 tablet:grid-cols-4 pc:grid-cols-8 gap-3.5
px-[8px] mt-0 mx-auto ">
{idols.slice(currentPage * itemsPerPage, (currentPage + 1) * itemsPerPage).map((idol) => {
const isDisabled = favoriteIdols.includes(idol.id);

return (
<div key={idol.id} className={`relative transition-opacity duration-300 ${isDisabled ? 'opacity-50' : ''}`}>
<CheckedIdolCard
idol={idol}
isSelectable={!isDisabled}
isSelected={selectedIdols.includes(idol.id)}
isDisabled={isDisabled}
onClick={(e) => {
if (isDisabled) {
e.preventDefault();
return;
}
handleToggle(idol.id);
}}
/>
</div>
);
})}
</div>
<div
className="grid grid-cols-3 tablet:grid-cols-4 pc:grid-cols-8 gap-3.5
px-[8px] mt-0 mx-auto "
>
{idols
.slice(currentPage * itemsPerPage, (currentPage + 1) * itemsPerPage)
.map((idol) => {
const isDisabled = favoriteIdols.includes(idol.id);

return (
<div
key={idol.id}
className={`relative transition-opacity duration-300 ${isDisabled ? 'opacity-50' : ''}`}
>
<IdolCard
idol={idol}
isSelectable={!isDisabled}
isSelected={selectedIdols.includes(idol.id)}
isDisabled={isDisabled}
onClick={(e) => {
if (isDisabled) {
e.preventDefault();
return;
}
handleToggle(idol.id);
}}
/>
</div>
);
})}
</div>

<button
onClick={nextPage}
disabled={(currentPage + 1) * itemsPerPage >= idols.length}
className="absolute right-[1%] tablet:right-[1.5%] pc:right-[-4.5%] top-1/2 transform -translate-y-1/2
<button
onClick={nextPage}
disabled={(currentPage + 1) * itemsPerPage >= idols.length}
className="absolute right-[1%] tablet:right-[1.5%] pc:right-[-4.5%] top-1/2 transform -translate-y-1/2
bg-[rgba(27,27,27,0.8)] hover:bg-[rgba(27,27,27,1)] transition-all w-[29px] h-[135px]
rounded-[4px] flex items-center justify-center"
>
<img
src={nextIcon}
alt="Next"
className="w-[6px] h-[12px] object-contain"
/>
</button>
>
<img
src={nextIcon}
alt="Next"
className="w-[6px] h-[12px] object-contain"
/>
</button>
</div>


<PrimaryButton
onClickFunc={handleAddToFavorites}
<PrimaryButton
onClickFunc={handleAddToFavorites}
className="w-[255px] h-[48px] mt-10 text-white rounded-full font-bold
bg-gradient-to-r from-pink-500 to-red-500 hover:opacity-90"
>
Expand Down