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
14 changes: 11 additions & 3 deletions src/components/CardModal.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,21 @@ import styles from './CardModal.module.scss';
import Modal from '@/components/Modal';
import SenderProfile from '@/components/SenderProfile';
import Editor from '@/components/Editor/Editor';
import Button from './Button/Button';

const CardModal = ({ modalItems, onClose }) => {
const { sender, imageUrl, createdAt, content, font } = modalItems;
const { sender, relationship, imageUrl, createdAt, content, font } = modalItems;
console.log('CardModal', modalItems);

return (
<Modal className={styles['modal-styler']}>
<Modal.headerArea className={styles['header-area']}>
<SenderProfile sender={sender} imageUrl={imageUrl} createdAt={createdAt} />
<SenderProfile
sender={sender}
imageUrl={imageUrl}
createdAt={createdAt}
relationship={relationship}
/>
</Modal.headerArea>
<Modal.divider />
<Modal.contentArea>
Expand All @@ -19,7 +25,9 @@ const CardModal = ({ modalItems, onClose }) => {
</div>
</Modal.contentArea>
<Modal.buttonArea className={styles['button-area']}>
<button onClick={onClose}>확인</button>
<Button size={'medium'} variant={'primary'} onClick={onClose}>
확인
</Button>
</Modal.buttonArea>
</Modal>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
display: inline-flex;
align-items: center;
justify-content: center;
background: #666666;
background-color: rgba(0,0,0,0.54);
border-radius: 16px;
color: #ffffff;
white-space: nowrap;
Expand Down
3 changes: 2 additions & 1 deletion src/contexts/ModalProvider.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ export const ModalProvider = ({ children }) => {

useEffect(() => {
if (!isOpen) return;
if (isClosing) return;
const handleMouseDown = (e) => {
if (modalWrapperRef.current?.contains(e.target)) {
isMouseDownInsideModal.current = true;
Expand Down Expand Up @@ -85,7 +86,7 @@ export const ModalProvider = ({ children }) => {
document.removeEventListener('mousedown', handleMouseDown);
document.removeEventListener('mouseup', handleMouseUp);
};
}, [isOpen]);
}, [isOpen, isClosing]);

//Modal이 열렸을 때 esc를 누르면 Modal Close
useEffect(() => {
Expand Down
24 changes: 24 additions & 0 deletions src/pages/HomePage/HomePage.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,11 @@ body {
width: 1200px;
padding: 90px;
overflow: hidden;
animation: slide-in-left 1s ease;

&--reverse {
flex-direction: row-reverse;
animation: slide-in-right 1s ease;
}

&__context {
Expand Down Expand Up @@ -111,3 +113,25 @@ body {
}
}
}

@keyframes slide-in-left {
0% {
opacity: 0.5;
transform: translateX(50px);
}
100% {
opacity: 1;
transform: translateX(0);
}
}

@keyframes slide-in-right {
0% {
opacity: 0.5;
transform: translateX(-50px);
}
100% {
opacity: 1;
transform: translateX(0);
}
}
73 changes: 54 additions & 19 deletions src/pages/ListPage/components/ItemCard.jsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
// src/components/ItemCard/ItemCard.jsx
import React from 'react';
import { Link } from 'react-router-dom';
import styles from './ItemCard.module.scss';
import ShowAvatars from './ShowAvatars';
import ShowEmoji from './ShowEmoji';
import { getBackgroundStylesFromPostData } from '@/utils/getBackgroundStylesFromPostData';
import { getContentStylesFromPostData } from '@/utils/getContentStylesFromPostData';
import { getIsCardDarkFromPostData } from '../../../utils/getIsCardDarkFromPostData';

const ItemCard = ({
id,
Expand All @@ -24,43 +23,79 @@ const ItemCard = ({
// 이미지: 하얀색 텍스트 / 어두운색 overlay 적용
const contentStyle = getContentStylesFromPostData(backgroundImageURL);

//카드가 밝은 색인지 어두운 색인지 판별
//이미지: true
//어두운 색: true
//밝은 색: false
const isCardDark = getIsCardDarkFromPostData(backgroundImageURL);

//isCardDark true: 밝은색 선
//isCardDark false: 어두운색 선
const myDivClassName = isCardDark
? `${styles['item-card__myDiv']} ${styles['card-dark']}`
: `${styles['item-card__myDiv']} ${styles['card-light']}`;

return (
<Link to={`/post/${id}`} className={styles['item-card__link']}>
<div className={styles['item-card']} style={backgroundStyle}>
{/* 밝은조명 효과 */}
<div className={styles['item-card__shinning']} style={isCardDark ? { opacity: 0.4 } : {}} />
{/* 어두운 음영 효과 */}
<div className={styles['item-card__shadow']} style={isCardDark ? { opacity: 0.4 } : {}} />
<div className={styles['item-card__content']} style={contentStyle}>
<h3 className={styles['item-card__title']}>To. {name}</h3>
<p className={styles['item-card__meta']}>{messageCount}명이 작성했어요!</p>

{/* 프로필 아바타 영역 (최대 3) */}
{recentMessages.length > 0 ? (
<div className={styles['item-card__avatars-area']}>
{/* 프로필 아바타 영역 (최대 3) */}

<ShowAvatars
profiles={recentMessages}
totalCount={messageCount}
loading={false}
error={null}
/>
) : (
<div
className={styles['item-card__avatars-placeholder']}
style={{ minHeight: '32px' }}
/>
)}
</div>

<div className={styles['item-card__myDiv']} />
<p className={styles['item-card__meta']}>
{!messageCount ? (
`아직 받은 메세지가 없어요🥲`
) : (
<span>
<strong style={{ fontWeight: 700 }}>{messageCount}</strong>명이 작성했어요!
</span>
)}
</p>

<div className={myDivClassName} />

{/* 반응 이모지 영역 (최대 3) */}
{topReactions.length > 0 ? (
<div className={styles['item-card__emojis-area']}>
<ShowEmoji emojis={topReactions} />
) : (
<div
className={styles['item-card__reactions-placeholder']}
style={{ minHeight: '24px' }}
/>
)}
</div>
</div>
</div>
</Link>
);
};

const Skeleton = () => {
return (
<div className={styles['skeleton-card']}>
<div className={styles['skeleton-card__content']}>
<div className={styles['skeleton-card__title']} />
<div className={styles['skeleton-card__profile']} />
<div className={styles['skeleton-card__meta']} />
<div className={styles['skeleton-card__myDiv']} />
<div className={styles['skeleton-card__emojis-area']}>
{new Array(3).fill(0).map((_, i) => (
<div key={i} className={styles['skeleton-card__emoji']} />
))}
</div>
</div>
</div>
);
};

ItemCard.skeleton = Skeleton;

export default ItemCard;
114 changes: 108 additions & 6 deletions src/pages/ListPage/components/ItemCard.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,36 @@
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;
}

&__content {
display: flex;
flex-direction: column;
justify-content: center;
gap: 10px;
gap: 12px;
height: 100%;
padding: 30px 24px;
padding: 30px 24px 20px;
color: var(--color-gray-900);
}

Expand All @@ -39,13 +60,27 @@
margin: 0;
font-size: var(--font-size-24);
font-weight: var(--font-weight-bold);
line-height: 36px;
height:36px;
}

&__avatars-area {
height: 29px;
}

&__meta {
margin: 4px 0;
font-size: var(--font-size-16);
line-height: 26px;
height: 26px;
flex-grow: 1;
}

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

&__top-reactions {
display: flex;
gap: 8px;
Expand All @@ -64,6 +99,73 @@
&__myDiv {
width: 100%;
margin: 1% 0;
border: 0.5px solid rgba(0, 0, 0, 0.12);
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);
}
}
}

.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);

&__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 {
display: flex;
align-items: center;
gap: 8px;
height: 36px;
}

&__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);
}
}
4 changes: 4 additions & 0 deletions src/pages/ListPage/components/Slider.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ const Slider = ({ cards, hasNext, loadMore }) => {
<div className={styles['slider__container']}>
{isDesktop ? (
<div className={styles['slider__track']}>
{visibleCards.length === 0 &&
new Array(4).fill(0).map((_, i) => <ItemCard.skeleton key={i} />)}
{visibleCards.map((card) => (
<ItemCard
key={card.id}
Expand All @@ -62,6 +64,8 @@ const Slider = ({ cards, hasNext, loadMore }) => {
scrollObserverRef={scrollObserverRef}
>
<div className={styles['slider__track']}>
{visibleCards.length === 0 &&
new Array(4).fill(0).map((_, i) => <ItemCard.skeleton key={i} />)}
{visibleCards.map((card) => (
<ItemCard
key={card.id}
Expand Down
2 changes: 1 addition & 1 deletion src/pages/ListPage/components/Slider.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
&__track {
display: flex;
gap: 16px;
padding: 8px;
padding: 8px 0;
overflow: visible;
}
}
1 change: 1 addition & 0 deletions src/pages/RollingPaperItemPage/components/ListCard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const ListCard = ({ cardData, showDelete, onClick, onDelete }) => {
sender,
imageUrl: profileImageURL,
createdAt: formatDateKRW(createdAt),
relationship: relationship,
content: content,
font: font,
});
Expand Down
Loading
Loading