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
5 changes: 0 additions & 5 deletions src/components/IdolCard.jsx
Copy link
Collaborator

Choose a reason for hiding this comment

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

😂

Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,6 @@ const IdolCard = ({
</>
)}
</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
5 changes: 3 additions & 2 deletions src/components/Modal.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ function Modal({ title, onClose, children }) {

if (title.includes('아이돌') && isMobile) {
return (
<div className="fixed flex flex-col top-0 left-0 size-full bg-midnightBlack">
// z-[9999] : 모달창이 열렸을 때 리스트 페이지에 있는 아이돌 이미지 보더가 같이 보이는 현상 해결을 위해 작성
<div className="fixed flex flex-col top-0 left-0 size-full bg-midnightBlack z-[9999]">
Comment on lines -28 to +29
Copy link
Owner

@yoonc01 yoonc01 Feb 10, 2025

Choose a reason for hiding this comment

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

여기서 idolCard에 있는 border의 z인덱스를 지우는 것은 어떤가용 그게 필요가 없어 보이는 거 같아서요!

<img
src={leftTopGradient}
alt="leftTopGradient"
Expand All @@ -52,7 +53,7 @@ function Modal({ title, onClose, children }) {
}

return (
<div className="fixed top-0 left-0 w-[100%] h-[100%] flex justify-center items-center bg-midnightBlack/80 font-pretendard">
<div className="fixed top-0 left-0 w-[100%] h-[100%] flex justify-center items-center bg-midnightBlack/80 font-pretendard z-[9999]">
<div className="relative bg-deepCharcoal p-[20px] rounded-[8px] py-[24px] px-[16px]">
<img
src={closeButton}
Expand Down
12 changes: 8 additions & 4 deletions src/components/modalContent/MonthlyChartVoteList.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,19 @@ const MonthlyChartVoteList = ({

return (
<div
style={{ height: isMobile ? 'calc(100vh - 156px)' : '693px' }}
className={`flex flex-col overflow-y-scroll scrollbar-hidden w-full mt-[24px] ${isMobile ? 'mb-[40px]' : 'mb-[400px]'}`}
className={`flex flex-col overflow-y-scroll scrollbar-hidden w-full mt-[24px] ${isMobile ? 'h-full mb-[40px]' : 'h-[693px] mb-[400px]'}`}
>
{idols.map((idol, idx) => (
<div key={idol.id} onClick={() => setSelectedIdol(idol.id)}>
<MonthlyChartItem idol={idol} rank={idx + 1} layout="vote">
<MonthlyChartItem
idol={idol}
rank={idx + 1}
layout="vote"
selectedIdol={selectedIdol}
>
<div className="relative flex items-center justify-center">
<div
className={`w-[16px] h-[16px] rounded-full border-[2px] bg-gray-100 border-gray-300 ${selectedIdol === idol.id ? 'border-coralRed' : ''} flex items-center justify-center`}
className={`w-[16px] h-[16px] rounded-full border-[1px] bg-gray-100 ${selectedIdol === idol.id ? 'border-coralRed' : ''} flex items-center justify-center`}
>
<div
className={`absolute w-2 h-2 rounded-full bg-coralRed transition-transform ${selectedIdol === idol.id ? 'scale-100' : 'scale-0'}`}
Expand Down
64 changes: 38 additions & 26 deletions src/components/modalContent/MonthlyChartVoteModal.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,14 @@ import { useState, useEffect, useRef } from 'react';
import MonthlyChartVoteList from '@/components/modalContent/MonthlyChartVoteList';
import { getLists, postVotes } from '@/apis/monthlyChartApi';
import PrimaryButton from '@/components/PrimaryButton';
import { spendCredits } from '../../utils/creditStorage';
import { spendCredits, rechargeCredits } from '@/utils/creditStorage';

const MonthlyChartVoteModal = ({ gender, onClickVoteCredit, closeModal }) => {
const MonthlyChartVoteModal = ({
gender,
closeModal,
setModalStep,
setVoteTrigger,
}) => {
const [cursor, setCursor] = useState(0);
const [idolData, setIdolData] = useState([]);
const [loading, setLoading] = useState(false);
Expand Down Expand Up @@ -32,18 +37,20 @@ const MonthlyChartVoteModal = ({ gender, onClickVoteCredit, closeModal }) => {
const handleVoteClick = async () => {
const result = spendCredits(1000);
if (result === 'NOT-ENOUGH') {
alert('앗! 투표하기 위한 크레딧이 부족해요');
} else {
try {
const voteResult = await postVotes(selectedIdol);
alert('투표 완료!');
setModalStep('creditNotEnough');
return;
}

if (onClickVoteCredit) onClickVoteCredit();
closeModal();
} catch (error) {
console.error(error);
alert('투표에 실패했습니다. 다시 시도해 주세요.');
}
try {
await postVotes(selectedIdol);
alert('투표 완료!');
setVoteTrigger((prev) => !prev);

closeModal();
} catch (error) {
alert('투표에 실패했습니다. 다시 시도해 주세요.');
rechargeCredits(1000);
return;
}
};

Expand All @@ -68,7 +75,9 @@ const MonthlyChartVoteModal = ({ gender, onClickVoteCredit, closeModal }) => {

const observer = new IntersectionObserver(
(entries) => {
if (entries[0].isIntersecting) loadIdolData();
if (entries[0].isIntersecting) {
loadIdolData();
}
},
{ threshold: 0.2 }
);
Expand All @@ -78,25 +87,28 @@ const MonthlyChartVoteModal = ({ gender, onClickVoteCredit, closeModal }) => {

return (
<div
className={`relative overflow-hidden ${isMobile ? 'w-[calc(100%-24px)] h-full' : 'w-[525px] h-[693px]'}`}
className={`relative overflow-hidden ${isMobile ? 'W-full h-full' : 'w-[525px] h-[693px]'}`}
>
{loading ? (
<div className="text-center text-white">로딩 중입니다...</div>
) : (
<MonthlyChartVoteList
idols={idolData}
selectedIdol={selectedIdol}
setSelectedIdol={setSelectedIdol}
<div
className={`overflow-y-auto ${isMobile ? 'h-[calc(100vh-156px)]' : 'h-[600px]'}`}
>
<div
className="w-full h-[40px]"
ref={cursor !== null ? observerRef : null}
></div>
</MonthlyChartVoteList>
<MonthlyChartVoteList
idols={idolData}
selectedIdol={selectedIdol}
setSelectedIdol={setSelectedIdol}
>
<div
className="w-full h-[40px]"
ref={cursor !== null ? observerRef : null}
></div>
</MonthlyChartVoteList>
</div>
)}
<div
style={{ width: isMobile ? 'calc(100vw - 68px)' : '525px' }}
className={`absolute text-white leading-[26px] ${isMobile ? 'bottom-[64px] h-[112px] bg-midnightBlack' : 'bottom-0 h-[72px] bg-deepCharcoal'}`}
className={`absolute text-white leading-[26px] ${isMobile ? 'bottom-[64px] w-full h-[112px] bg-midnightBlack' : 'bottom-0 w-[525px] h-[72px] bg-deepCharcoal'}`}
>
<PrimaryButton
onClickFunc={handleVoteClick}
Expand Down
14 changes: 11 additions & 3 deletions src/pages/listPage/ListPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import DonationModalContent from '@/components/modalContent/DonationModalContent
import leftTopGradient from '@/assets/images/leftTopGradient.webp';
import DonationSuccess from '@/components/modalContent/DonationSuccess';
import MonthlyChartSection from '@/pages/listPage/monthlyChart/MonthlyChartSection';
import MonthlyChartVoteModal from '../../components/modalContent/MonthlyChartVoteModal';
import MonthlyChartVoteModal from '@/components/modalContent/MonthlyChartVoteModal';

function ListPage() {
const [isModalOpen, setIsModalOpen] = useState(false);
Expand All @@ -20,10 +20,11 @@ function ListPage() {
const [selectedAmount, setSelectedAmount] = useState(null);
const [selectedItem, setSelectedItem] = useState(null);
const [gender, setGender] = useState('female');
const [voteTrigger, setVoteTrigger] = useState(false);

useEffect(() => {
setCredits(getCredits());
}, []);
}, [modalStep]);

const openModal = (step, item = null) => {
setModalStep(step);
Expand Down Expand Up @@ -81,6 +82,8 @@ function ListPage() {
}}
gender={gender}
setGender={setGender}
voteTrigger={voteTrigger}
setVoteTrigger={setVoteTrigger}
/>

{isModalOpen && (
Expand Down Expand Up @@ -115,7 +118,12 @@ function ListPage() {
<DonationSuccess onConfirm={closeModal} />
)}
{modalStep === 'vote' && (
<MonthlyChartVoteModal closeModal={closeModal} gender={gender} />
<MonthlyChartVoteModal
closeModal={closeModal}
gender={gender}
setModalStep={setModalStep}
setVoteTrigger={setVoteTrigger}
/>
)}
</Modal>
)}
Expand Down
52 changes: 33 additions & 19 deletions src/pages/listPage/monthlyChart/MonthlyChartItem.jsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,25 @@
const MonthlyChartItem = ({ idol, rank, layout = 'default', children }) => {
const { profilePicture, name, group, totalVotes } = idol;
import IdolCard from '@/components/IdolCard';
import checkIcon from '@/assets/images/check.png';

const MonthlyChartItem = ({
idol,
rank,
layout = 'default',
children,
selectedIdol,
}) => {
const { name, group, totalVotes } = idol;

return (
<div className="flex items-center justify-between w-full text-[14px] pc:text-[16px] leading-[16.71px] pc:leading-[19.09px]">
{layout === 'default' ? (
<div className="flex w-full h-[70px] justify-between items-center">
<div className="flex items-center gap-[12px] font-medium">
<div className="rounded-full border-[1px] border-coralRed">
<div className="rounded-full border-[4px] border-midnightBlack">
<img
src={profilePicture}
alt={name}
className="items-center w-[60px] h-[60px] rounded-full"
/>
</div>
</div>
<IdolCard
idol={idol}
isSelected={false}
sizeClass="w-[70px] h-[70px]"
/>
<h4 className="text-coralRed">{rank}</h4>
<div className="flex justify-between w-max">
<p className="text-white/[0.87]">
Expand All @@ -29,14 +34,23 @@ const MonthlyChartItem = ({ idol, rank, layout = 'default', children }) => {
) : (
<div className="flex justify-between items-center w-full py-[4px]">
<div className="flex items-center justify-center gap-[12px] font-medium">
<div className="rounded-full border-[1px] border-coralRed">
<div className="rounded-full border-[4px] border-midnightBlack">
<img
src={profilePicture}
alt={name}
className="items-center w-[60px] h-[60px] rounded-full"
/>
</div>
<div className="relative">
<IdolCard
idol={idol}
isSelected={selectedIdol === idol.id}
sizeClass="w-[70px] h-[70px]"
isSelectable={false}
/>
{selectedIdol === idol.id && (
<div className="absolute inset-0 m-1.5 rounded-full overflow-hidden z-10">
<div className="w-full h-full bg-gradient-to-r from-coralRed to-pinkPunch opacity-50" />
<img
src={checkIcon}
alt="check"
className="absolute w-[16px] h-[16px] top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 z-20"
/>
</div>
)}
</div>
<h4 className="text-coralRed">{rank}</h4>
<div>
Expand Down
20 changes: 18 additions & 2 deletions src/pages/listPage/monthlyChart/MonthlyChartSection.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,13 @@ import { getLists } from '@/apis/monthlyChartApi';
import PrimaryButton from '@/components/PrimaryButton';
import MonthlyChartList from '@/pages/listPage/monthlyChart/MonthlyChartList';

const MonthlyChartSection = ({ onClickVote, gender, setGender }) => {
const MonthlyChartSection = ({
onClickVote,
gender,
setGender,
voteTrigger,
setVoteTrigger,
}) => {
const [cursor, setCursor] = useState(0);
const [idolData, setIdolData] = useState([]);
const [loading, setLoading] = useState(false);
Expand All @@ -27,8 +33,10 @@ const MonthlyChartSection = ({ onClickVote, gender, setGender }) => {

const loadIdolData = async () => {
setLoading(true);
console.log('loadIdolData:', gender, voteTrigger, cursor);
const cursorValue = voteTrigger ? 0 : cursor;
try {
const response = await getLists(gender, cursor, pageSize);
const response = await getLists(gender, cursorValue, pageSize);
if (cursor !== 0) {
setIdolData((prev) => [...prev, ...response.idols]);
} else {
Expand All @@ -39,6 +47,7 @@ const MonthlyChartSection = ({ onClickVote, gender, setGender }) => {
console.error(error);
} finally {
setLoading(false);
setVoteTrigger(false);
}
};

Expand All @@ -56,6 +65,13 @@ const MonthlyChartSection = ({ onClickVote, gender, setGender }) => {
loadIdolData();
}, [gender, pageSize]);

useEffect(() => {
if (voteTrigger) {
setIdolData([]);
loadIdolData();
}
}, [voteTrigger]);

useEffect(() => {
window.addEventListener('resize', updateChartSize);

Expand Down