Skip to content

Commit

Permalink
Feat/raffle details JMarketYard#25 (JMarketYard#52)
Browse files Browse the repository at this point in the history
Feat: 홈페이지 API 연결 JMarketYard#3
  • Loading branch information
yelynnn committed Feb 6, 2025
1 parent ff130e7 commit 7e28b13
Show file tree
Hide file tree
Showing 10 changed files with 268 additions and 172 deletions.
5 changes: 2 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

95 changes: 51 additions & 44 deletions src/components/ProductCard.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import React, { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import styled from 'styled-components';
import ticket from '../assets/ProductCard/ticket.svg';
import icLike from '../assets/ProductCard/like.svg';
import icUnlike from '../assets/ProductCard/unlike.svg';
import { Link } from 'react-router-dom';
import RaffleProps from './RaffleProps';

const getFormatTime = (seconds: number): string => {
const hours = Math.floor(seconds / 3600);
Expand All @@ -18,20 +21,9 @@ const getFormatTime = (seconds: number): string => {
return `${remainingSeconds}초`;
};

interface ProductProps {
raffleId: number;
imageUrl: string;
name: string;
ticketNum: number;
timeUntilEnd: number;
finish: boolean;
participantNum: number;
like: boolean;
}

const ProductCard: React.FC<ProductProps> = ({
const ProductCard: React.FC<RaffleProps> = ({
raffleId,
imageUrl,
imageUrls,
name,
ticketNum,
timeUntilEnd,
Expand All @@ -40,37 +32,42 @@ const ProductCard: React.FC<ProductProps> = ({
like,
}) => {
const [isLiked, setIsLiked] = useState(false);
const toggleLike = () => {
const navigate = useNavigate();
const toggleLike = (event: React.MouseEvent<HTMLDivElement>) => {
event.stopPropagation(); //Wrapper로 이벤트 전달 방지
event.preventDefault(); // 기본 동작 (Link 이동) 방지
setIsLiked((prevState) => !prevState);
};

return (
<Wrapper>
<ImageContainer>
{finish && <RaffleClosingBox>응모 마감</RaffleClosingBox>}
{timeUntilEnd > 0 && timeUntilEnd <= 86400 && (
<TextBox>마감임박</TextBox>
)}
<LikeBox onClick={toggleLike}>
<img
src={isLiked ? icLike : icUnlike}
alt={isLiked ? 'Liked' : 'Unliked'}
/>
</LikeBox>
</ImageContainer>
<InfoContainer>
<TitleContainer>
<TitleBox>{name}</TitleBox>
<ParticipantsBox>{participantNum}명 응모중</ParticipantsBox>
</TitleContainer>

<ContentContainer>
<TicketBox>
<img src={ticket} alt="ticket" /> {ticketNum}
</TicketBox>
{!finish && <TimeBox>{getFormatTime(timeUntilEnd)}뒤 마감</TimeBox>}
</ContentContainer>
</InfoContainer>
<StyledLink to={`raffles/${raffleId}`}>
<ImageContainer imageUrls={imageUrls}>
{finish && <RaffleClosingBox>응모 마감</RaffleClosingBox>}
{timeUntilEnd > 0 && timeUntilEnd <= 86400 && (
<TextBox>마감임박</TextBox>
)}
<LikeBox onClick={toggleLike}>
<img
src={isLiked ? icLike : icUnlike}
alt={isLiked ? 'Liked' : 'Unliked'}
/>
</LikeBox>
</ImageContainer>
<InfoContainer>
<TitleContainer>
<TitleBox>{name}</TitleBox>
<ParticipantsBox>{participantNum}명 응모중</ParticipantsBox>
</TitleContainer>

<ContentContainer>
<TicketBox>
<img src={ticket} alt="ticket" /> {ticketNum}
</TicketBox>
{!finish && <TimeBox>{getFormatTime(timeUntilEnd)}뒤 마감</TimeBox>}
</ContentContainer>
</InfoContainer>
</StyledLink>
</Wrapper>
);
};
Expand All @@ -85,14 +82,26 @@ const Wrapper = styled.div`
background: #fff;
`;

const ImageContainer = styled.div`
const StyledLink = styled(Link)`
text-decoration: none; /* 밑줄 제거 */
color: inherit; /* 기본 색상 유지 */
`;

const ImageContainer = styled.div.attrs<Pick<RaffleProps, 'imageUrls'>>(
({ imageUrls }) => ({
style: { backgroundImage: `url(${imageUrls[0]})` },
}),
)<Pick<RaffleProps, 'imageUrls'>>`
width: 228px;
height: 227px;
flex-shrink: 0;
border-radius: 5px;
background: #e4e4e4;
position: relative;
margin-top: 6px;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
`;

const RaffleClosingBox = styled.div`
Expand Down Expand Up @@ -152,9 +161,7 @@ const LikeBox = styled.div`
position: absolute;
top: 188px;
right: 16px;
/* cursor: pointer;
user-select: none; */
cursor: pointer;
`;

const InfoContainer = styled.div`
Expand Down
13 changes: 13 additions & 0 deletions src/components/RaffleProps.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
interface RaffleProps {
raffleId: number;
imageUrls: string[];
name: string;
ticketNum: number;
timeUntilEnd: number;
finish: boolean;
participantNum: number;
like: boolean;
children?: React.ReactNode;
}

export default RaffleProps;
80 changes: 41 additions & 39 deletions src/components/SmallProductCard.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import React, { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import styled from 'styled-components';
import smallTicket from '../assets/smallProductCard/smallTicket.svg';
import smallUnlike from '../assets/smallProductCard/smallUnlike.svg';
import smallLike from '../assets/smallProductCard/smallLike.svg';
import { Link } from 'react-router-dom';
import RaffleProps from './RaffleProps';

const getFormatTime = (seconds: number): string => {
const hours = Math.floor(seconds / 3600);
Expand All @@ -18,20 +21,9 @@ const getFormatTime = (seconds: number): string => {
return `${remainingSeconds}초`;
};

interface ProductProps {
raffleId: number;
imageUrl: string;
name: string;
ticketNum: number;
timeUntilEnd: number;
finish: boolean;
participantNum: number;
like: boolean;
}

const SmallProductCard: React.FC<ProductProps> = ({
const SmallProductCard: React.FC<RaffleProps> = ({
raffleId,
imageUrl,
imageUrls,
name,
ticketNum,
timeUntilEnd,
Expand All @@ -40,32 +32,37 @@ const SmallProductCard: React.FC<ProductProps> = ({
like,
}) => {
const [isLiked, setIsLiked] = useState(false);
const toggleLike = () => {
const toggleLike = (event: React.MouseEvent<HTMLDivElement>) => {
event.stopPropagation(); //Wrapper로 이벤트 전달 방지
event.preventDefault(); // 기본 동작 (Link 이동) 방지
setIsLiked((prevState) => !prevState);
};

return (
<Wrapper>
<ImageContainer imageUrl={imageUrl}>
{finish && <RaffleClosingBox>응모 마감</RaffleClosingBox>}
{timeUntilEnd > 0 && timeUntilEnd <= 86400 && (
<TextBox>마감임박</TextBox>
)}
<LikeBox onClick={toggleLike}>
<img
src={isLiked ? smallLike : smallUnlike}
alt={isLiked ? 'Liked' : 'Unliked'}
/>
</LikeBox>
</ImageContainer>
<Layout>
<TitleContainer>{name}</TitleContainer>
<InfoContainer>
<TicketBox>
<img src={smallTicket} alt="smallTicket" /> {ticketNum}
</TicketBox>
{!finish && <TimeBox>{getFormatTime(timeUntilEnd)}뒤 마감</TimeBox>}
</InfoContainer>
</Layout>
<StyledLink to={`raffles/${raffleId}`}>
<ImageContainer imageUrls={imageUrls}>
{finish && <RaffleClosingBox>응모 마감</RaffleClosingBox>}
{timeUntilEnd > 0 && timeUntilEnd <= 86400 && (
<TextBox>마감임박</TextBox>
)}
<LikeBox onClick={toggleLike}>
<img
src={isLiked ? smallLike : smallUnlike}
alt={isLiked ? 'Liked' : 'Unliked'}
/>
</LikeBox>
</ImageContainer>
<Layout>
<TitleContainer>{name}</TitleContainer>
<InfoContainer>
<TicketBox>
<img src={smallTicket} alt="smallTicket" /> {ticketNum}
</TicketBox>
{!finish && <TimeBox>{getFormatTime(timeUntilEnd)}뒤 마감</TimeBox>}
</InfoContainer>
</Layout>
</StyledLink>
</Wrapper>
);
};
Expand All @@ -78,11 +75,16 @@ const Wrapper = styled.div`
background-color: #ffffff;
`;

const ImageContainer = styled.div.attrs<Pick<ProductProps, 'imageUrl'>>(
({ imageUrl }) => ({
style: { backgroundImage: `url(${imageUrl})` },
const StyledLink = styled(Link)`
text-decoration: none; /* 밑줄 제거 */
color: inherit; /* 기본 색상 유지 */
`;

const ImageContainer = styled.div.attrs<Pick<RaffleProps, 'imageUrls'>>(
({ imageUrls }) => ({
style: { backgroundImage: `url(${imageUrls[0]})` },
}),
)<Pick<ProductProps, 'imageUrl'>>`
)<Pick<RaffleProps, 'imageUrls'>>`
width: 192px;
height: 192px;
flex-shrink: 0;
Expand Down
Loading

0 comments on commit 7e28b13

Please sign in to comment.