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
15 changes: 6 additions & 9 deletions src/hooks/useSliderPaging.jsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
// src/hooks/useSliderPaging.js
import { useState, useEffect, useMemo, useCallback } from 'react';
import { useState, useMemo, useCallback } from 'react';
import { useDeviceType } from '@/hooks/useDeviceType';

export function useSliderPaging({ totalItems, pageSize, breakpoint = 1200 }) {
// 1) 뷰포트 모드(데스크톱/모바일) 감지
const [isDesktop, setIsDesktop] = useState(window.innerWidth >= breakpoint);
useEffect(() => {
const handler = () => setIsDesktop(window.innerWidth >= breakpoint);
window.addEventListener('resize', handler);
return () => window.removeEventListener('resize', handler);
}, [breakpoint]);
export function useSliderPaging({ totalItems, pageSize }) {
// deviceType을 통한 데스크톱 여부 감지
const deviceType = useDeviceType();
const isDesktop = deviceType === 'desktop';

// 2) 페이지 인덱스 관리
const [pageIndex, setPageIndex] = useState(0);
Expand Down
17 changes: 9 additions & 8 deletions src/pages/ListPage/ListPage.jsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import Slider from './components/Slider';
import styles from './ListPage.module.scss';
import { Link } from 'react-router-dom';
import Button from '@/components/Button/Button';

import { listRecipients } from '@/apis/recipientsApi';
import { useApi } from '@/hooks/useApi';

const ListPage = () => {
// 인기/최신 각각 오프셋·hasNext 관리
const navigate = useNavigate();
const [popularOffset, setPopularOffset] = useState(0);
const [recentOffset, setRecentOffset] = useState(0);
const [popularHasNext, setPopularHasNext] = useState(false);
Expand All @@ -21,7 +22,7 @@ const ListPage = () => {
refetch: getPopularList,
} = useApi(
listRecipients,
{ limit: 20, offset: popularOffset, sortLike: true },
{ limit: 8, offset: popularOffset, sortLike: true },
Copy link
Collaborator

Choose a reason for hiding this comment

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

페이지 반응형 breakpoint 수정, 인기순 8개 불러오는 점 확인하였습니다!

{
errorMessage: '인기 롤링페이퍼 목록을 불러오는 데 실패했습니다.',
retry: 1,
Expand Down Expand Up @@ -82,19 +83,19 @@ const ListPage = () => {
<div className={styles['list-page']}>
{/* 인기 롤링 페이퍼 🔥 */}
<section className={styles['list-page__section']}>
<h2 className={styles['list-page__title']}>인기 롤링 페이퍼 🔥</h2>
<Slider cards={popularCards} hasNext={popularHasNext} loadMore={loadMorePopular} />
<h2 className={styles['list-page__title']}> 요즘 가장 사랑받는 롤링 페이퍼 Top 8 💌</h2>
<Slider cards={popularCards} hasNext={false} loadMore={loadMorePopular} />
</section>

{/* 최근에 만든 롤링 페이퍼 ⭐️ */}
<section className={styles['list-page__section']}>
<h2 className={styles['list-page__title']}>최근에 만든 롤링 페이퍼 ⭐️</h2>
<h2 className={styles['list-page__title']}> 따끈따끈 신상 롤링 페이퍼 🍞</h2>
<Slider cards={recentCards} hasNext={recentHasNext} loadMore={loadMoreRecent} />
</section>

<Link to='/post'>
<Button className={styles['list-page__createButton']}>나도 만들어보기</Button>
</Link>
<Button className={styles['list-page__createButton']} onClick={() => navigate('/post')}>
나도 만들어보기
</Button>
</div>
);
};
Expand Down
6 changes: 3 additions & 3 deletions src/pages/ListPage/ListPage.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@
padding-top: 50px;
overflow: visible;

@media screen and (min-width: 768px) and (max-width: 1199px) {
@include tablet {
padding: 0 24px;
width: 100%;
min-height: 100dvh;
}

@media screen and (max-width: 767px) {
@include mobile {
padding: 0 20px;
width: 100%;
padding-top: 40px;
Expand Down Expand Up @@ -57,7 +57,7 @@
display: block; // inline → block으로 바꿔서 margin:auto 적용
margin: 0 auto;

@media screen and (min-width: 355px) and (max-width: 1199px) {
@include tablet {
width: 100%;
margin-bottom: 20px;
}
Expand Down
19 changes: 12 additions & 7 deletions src/pages/ListPage/components/ItemCard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,17 +48,21 @@ const ItemCard = ({
<div className={styles['item-card__avatars-area']}>
{/* 프로필 아바타 영역 (최대 3) */}

<ShowAvatars
profiles={recentMessages}
totalCount={messageCount}
loading={false}
error={null}
/>
{!messageCount ? (
<div style={{ paddingTop: '15px' }}>✨ 첫 글을 기다리고 있어요!</div>
) : (
<ShowAvatars
profiles={recentMessages}
totalCount={messageCount}
loading={false}
error={null}
/>
)}
</div>

<p className={styles['item-card__meta']}>
{!messageCount ? (
`아직 받은 메세지가 없어요🥲`
<div>따뜻한 한마디를 전해볼까요?</div>
) : (
<span>
<strong style={{ fontWeight: 700 }}>{messageCount}</strong>명이 작성했어요!
Expand All @@ -69,6 +73,7 @@ const ItemCard = ({
<div className={myDivClassName} />

{/* 반응 이모지 영역 (최대 3) */}

<div className={styles['item-card__emojis-area']}>
<ShowEmoji emojis={topReactions} />
</div>
Expand Down
186 changes: 100 additions & 86 deletions src/pages/ListPage/components/ItemCard.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -17,29 +17,29 @@
transform: translateZ(0);
&:hover {
transform: scale(1.05);
}

&__shinning {
position: absolute;
width: 90px;
height: 200px;
right: 20px;
top: 20px;
background-color: #ffffff;
filter: blur(60px);
z-index: -1;
}

&__shadow {
position: absolute;
width: 10px;
height: 200px;
left: 20px;
top: 20px;
background-color: #222222;
filter: blur(55px);
z-index: -1;
}
}

&__shinning {
position: absolute;
width: 90px;
height: 200px;
right: 20px;
top: 20px;
background-color: #ffffff;
filter: blur(60px);
z-index: -1;
}

&__shadow {
position: absolute;
width: 10px;
height: 200px;
left: 20px;
top: 20px;
background-color: #222222;
filter: blur(55px);
z-index: -1;
}

&__content {
display: flex;
Expand All @@ -60,26 +60,40 @@
margin: 0;
font-size: var(--font-size-24);
font-weight: var(--font-weight-bold);
line-height: 36px;
height:36px;
line-height: 36px;
height: 36px;
}

&__avatars-area {
height: 29px;
}

&__avatars-area {
height: 29px;
}

&__meta {
font-size: var(--font-size-16);
line-height: 26px;
height: 26px;
flex-grow: 1;
line-height: 26px;
height: 26px;
flex-grow: 1;
}
&__write {
width: 100%;
height: 40px;

&__emojis-area {
height: 36px;
display: flex;
align-items: center;
}
background-color: var(--color-purple-500);
border: none;
border-radius: 12px;
font-weight: 700;
font-size: 15px;
line-height: 28px;
color: var(--color-white);
align-self: center;
display: block; // inline → block으로 바꿔서 margin:auto 적용
margin: 0 auto;
}
&__emojis-area {
height: 36px;
display: flex;
align-items: center;
}

&__top-reactions {
display: flex;
Expand All @@ -100,72 +114,72 @@
width: 100%;
margin: 1% 0;
border-bottom: 1px solid rgba(0, 0, 0, 0.12);
&.card-dark {
border: 1px solid rgba(255, 255, 255, 0.4);
}
&.card-light {
border: 1px solid rgba(0, 0, 0, 0.12);
}
&.card-dark {
border: 1px solid rgba(255, 255, 255, 0.4);
}
&.card-light {
border: 1px solid rgba(0, 0, 0, 0.12);
}
}
}

.skeleton-card {
position: relative;
width: 275px;
height: 260px;
overflow: hidden;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
border-radius: 16px;
border: 1px solid rgba(0, 0, 0, 0.1);
transform: scale(1);
transition: transform 0.5s;
will-change: transform;
transform: translateZ(0);
position: relative;
width: 275px;
height: 260px;
overflow: hidden;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
border-radius: 16px;
border: 1px solid rgba(0, 0, 0, 0.1);
transform: scale(1);
transition: transform 0.5s;
will-change: transform;
transform: translateZ(0);

&__content {
display: flex;
flex-direction: column;
gap: 12px;
height: 100%;
padding: 30px 24px 20px;
}

&__title {
@include skeleton-style;
width: 100%;
height:36px;
}

&__profile {
@include skeleton-style;
width: 30%;
height: 30px;
border-radius: 16px;
}

&__meta {
@include skeleton-style;
height: 26px;
flex-grow: 1;
}

&__emojis-area {
}

&__title {
@include skeleton-style;
width: 100%;
height: 36px;
}

&__profile {
@include skeleton-style;
width: 30%;
height: 30px;
border-radius: 16px;
}

&__meta {
@include skeleton-style;
height: 26px;
flex-grow: 1;
}

&__emojis-area {
display: flex;
align-items: center;
gap: 8px;
height: 36px;
}
height: 36px;
}

&__emoji {
@include skeleton-style;
width: 64px;
height: 32px;
border-radius: 16px;
}
&__emoji {
@include skeleton-style;
width: 64px;
height: 32px;
border-radius: 16px;
}

&__myDiv {
width: 100%;
margin: 1% 0;
border: 1px solid rgba(0, 0, 0, 0.12);
border: 1px solid rgba(0, 0, 0, 0.12);
}
}
}
4 changes: 2 additions & 2 deletions src/pages/ListPage/components/Slider.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const Slider = ({ cards, hasNext, loadMore }) => {
const { isDesktop, pageIndex, canPrev, canNext, goPrev, goNext } = useSliderPaging({
totalItems: cards.length,
pageSize: PAGE_SIZE,
breakpoint: 1200,
breakpoint: 1248,
});

// 데스크탑: 현재 페이지*4 ~ 페이지*4+4 슬라이스
Expand All @@ -32,7 +32,7 @@ const Slider = ({ cards, hasNext, loadMore }) => {

return (
<div className={styles.slider}>
{isDesktop && (
{isDesktop && canPrev && (
<div className={styles['slider__arrow--left']}>
<ArrowButton direction='left' onClick={goPrev} disabled={!canPrev} />
</div>
Expand Down
Loading
Loading