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
64 changes: 36 additions & 28 deletions apps/client/src/pages/jobPins/JobPins.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,44 @@
import { Icon } from '@pinback/design-system/icons';
import { Balloon } from '@shared/components/balloon/Balloon';
import { Card } from '@pinback/design-system/ui';
import Footer from '@pages/myBookmark/components/footer/Footer';

const MOCK_JOB_PINS = Array.from({ length: 30 }, (_, index) => ({
id: index + 1,
title: '텍스트텍스트텍스트텍스트텍스트텍스트텍스트',
content: '서브텍스트입니다서브텍스트입니다서브텍스트입니다서브텍스트입니다',
category: '카테고리명',
categoryColor: 'COLOR7' as const,
variant: 'save' as const,
nickname: index % 3 === 0 ? '구글닉네임명' : '',
}));

const JobPins = () => {
return (
<div>
{' '}
<Balloon variant="main" side="bottom">
<div className="text-lg font-semibold">치삐가 방금</div>

<div className="text-sm opacity-90">도토리 1개를 모았어요!</div>
</Balloon>
<Balloon variant="gray" side="left" onClose={() => alert('닫힘')}>
<div className="text-lg font-semibold">치삐가 방금</div>
<div className="flex h-screen flex-col pl-[8rem] pr-[5rem] pt-[5.2rem]">
<div className="flex items-center gap-[1.2rem]">
<p className="head3">관심 직무 핀</p>
<p className="head3 text-main500">기획자</p>
</div>
<p className="body3-r text-font-gray-3 mt-[0.8rem]">
같은 직무의 사람들이 저장한 아티클을 살펴봐요. 선택한 직무를 기준으로
최신 핀이 업데이트 돼요!
</p>

<div className="text-sm opacity-90">도토리 1개를 모았어요!</div>
</Balloon>
<Balloon variant="gray" side="left">
<Icon name="ic_info" size={16} />
<div className="text-sm opacity-90">도토리 1개를 모았어요!</div>
</Balloon>
<Balloon variant="main" side="bottom">
<div className="flex items-center gap-3">
{/* 캐릭터 이미지 */}
<Icon name="chippi_profile" size={40} />
<div className="scrollbar-hide mt-[2.6rem] flex h-screen flex-wrap content-start gap-[1.6rem] overflow-y-auto scroll-smooth">
{MOCK_JOB_PINS.map((pin) => (
Comment on lines +16 to +27
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

wc -l apps/client/src/pages/jobPins/JobPins.tsx

Repository: Pinback-Team/pinback-client

Length of output: 115


🏁 Script executed:

cat -n apps/client/src/pages/jobPins/JobPins.tsx

Repository: Pinback-Team/pinback-client

Length of output: 1776


카드 리스트의 이중 스크롤 문제
부모 컨테이너는 h-screenflex-col 레이아웃이며, 내부 리스트 컨테이너도 h-screen으로 고정되어 있습니다. 헤더와 푸터의 높이까지 추가되면 전체 콘텐츠가 뷰포트를 초과하여 페이지와 리스트 모두에서 스크롤이 발생합니다. Flex 레이아웃에서 리스트는 flex-1 min-h-0으로 변경하여 남은 높이를 자동으로 차지하도록 조정해야 합니다.

🔧 제안 변경
-      <div className="scrollbar-hide mt-[2.6rem] flex h-screen flex-wrap content-start gap-[1.6rem] overflow-y-auto scroll-smooth">
+      <div className="scrollbar-hide mt-[2.6rem] flex flex-1 min-h-0 flex-wrap content-start gap-[1.6rem] overflow-y-auto scroll-smooth">
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<div className="flex h-screen flex-col pl-[8rem] pr-[5rem] pt-[5.2rem]">
<div className="flex items-center gap-[1.2rem]">
<p className="head3">관심 직무 핀</p>
<p className="head3 text-main500">기획자</p>
</div>
<p className="body3-r text-font-gray-3 mt-[0.8rem]">
같은 직무의 사람들이 저장한 아티클을 살펴봐요. 선택한 직무를 기준으로
최신 핀이 업데이트 돼요!
</p>
<div className="text-sm opacity-90">도토리 1개를 모았어요!</div>
</Balloon>
<Balloon variant="gray" side="left">
<Icon name="ic_info" size={16} />
<div className="text-sm opacity-90">도토리 1개를 모았어요!</div>
</Balloon>
<Balloon variant="main" side="bottom">
<div className="flex items-center gap-3">
{/* 캐릭터 이미지 */}
<Icon name="chippi_profile" size={40} />
<div className="scrollbar-hide mt-[2.6rem] flex h-screen flex-wrap content-start gap-[1.6rem] overflow-y-auto scroll-smooth">
{MOCK_JOB_PINS.map((pin) => (
<div className="flex h-screen flex-col pl-[8rem] pr-[5rem] pt-[5.2rem]">
<div className="flex items-center gap-[1.2rem]">
<p className="head3">관심 직무 핀</p>
<p className="head3 text-main500">기획자</p>
</div>
<p className="body3-r text-font-gray-3 mt-[0.8rem]">
같은 직무의 사람들이 저장한 아티클을 살펴봐요. 선택한 직무를 기준으로
최신 핀이 업데이트 돼요!
</p>
<div className="scrollbar-hide mt-[2.6rem] flex flex-1 min-h-0 flex-wrap content-start gap-[1.6rem] overflow-y-auto scroll-smooth">
{MOCK_JOB_PINS.map((pin) => (
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/client/src/pages/jobPins/JobPins.tsx` around lines 16 - 27, The inner
scrollable list div in JobPins.tsx (the element currently rendered with class
string containing "scrollbar-hide mt-[2.6rem] flex h-screen flex-wrap ...
overflow-y-auto") is fixed to h-screen causing double scroll; replace the height
utility with flexible sizing by removing "h-screen" and adding "flex-1 min-h-0"
so the list takes the remaining space in the parent flex-col and its
overflow-y-auto works correctly.

<Card
key={pin.id}
type="bookmark"
variant={pin.variant}
title={pin.title}
content={pin.content}
category={pin.category}
categoryColor={pin.categoryColor}
nickname={pin.nickname}
/>
))}
</div>

{/* 텍스트 영역 */}
<div className="flex flex-col">
<div className="text-[18px] font-semibold">치삐가 방금</div>
<div className="text-[16px]">도토리 1개를 모았어요!</div>
</div>
</div>
</Balloon>
<Footer />
</div>
);
};
Expand Down
27 changes: 27 additions & 0 deletions packages/design-system/src/components/card/Card.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,15 @@ const meta: Meta<typeof Card> = {
control: 'text',
if: { arg: 'type', eq: 'bookmark' },
},
variant: {
control: 'inline-radio',
options: ['default', 'save'],
if: { arg: 'type', eq: 'bookmark' },
},
nickname: {
control: 'text',
if: { arg: 'variant', eq: 'save' },
},
},
};

Expand All @@ -56,6 +65,7 @@ export const BookMark: Story = {
name: 'type: bookmark',
args: {
type: 'bookmark',
variant: 'default',
title: '북마크 카드 타이틀',
content: '북마크 컨텐츠 내용입니다.',
category: '디자인',
Expand All @@ -65,6 +75,20 @@ export const BookMark: Story = {
},
};

export const BookMarkSave: Story = {
name: 'type: bookmark (save)',
args: {
type: 'bookmark',
variant: 'save',
title: '북마크 카드 타이틀',
content: '북마크 컨텐츠 내용입니다.',
category: '디자인',
nickname: '하비',
imageUrl:
'https://images.unsplash.com/photo-1555949963-ff9fe0c870eb?q=80&w=2070&auto=format&fit=crop',
},
};

export const LongTextSideBySide: Story = {
name: 'case: Long Text',
render: () => (
Expand All @@ -79,6 +103,7 @@ export const LongTextSideBySide: Story = {
/>
<Card
type="bookmark"
variant="default"
title="두 줄로 표시되는 긴 북마크 카드 타이틀입니다. 제한 길이를 넘어가면 ... 처리가 됩니다."
content="여기에 두 줄 이상으로 늘어나는 북마크 컨텐츠 내용이 들어갑니다. 길이를 확인해보세요."
category="마케팅"
Expand All @@ -102,6 +127,7 @@ export const NoImageSideBySide: Story = {
/>
<Card
type="bookmark"
variant="default"
title="두 줄로 표시되는 긴 북마크 카드 타이틀입니다. 제한 길이를 넘어가면 ... 처리가 됩니다."
content="여기에 두 줄 이상으로 늘어나는 북마크 컨텐츠 내용이 들어갑니다. 길이를 확인해보세요."
category="마케팅"
Expand All @@ -115,6 +141,7 @@ export const NoCategoryBookmark: Story = {
name: 'case: No category (bookmark)',
args: {
type: 'bookmark',
variant: 'default',
title: '북마크 카드 타이틀',
content: '북마크 컨텐츠 내용입니다.',
date: '2025.08.26',
Expand Down
14 changes: 12 additions & 2 deletions packages/design-system/src/components/card/Card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,23 @@ type RemindProps = BaseProps & {
date?: never;
};

type BookmarkProps = BaseProps & {
type BookmarkDefaultProps = BaseProps & {
type: 'bookmark';
variant?: 'default';
date: string;
nickname?: never;
timeRemaining?: never;
};

export type CardProps = RemindProps | BookmarkProps;
type BookmarkSaveProps = BaseProps & {
type: 'bookmark';
variant: 'save';
nickname: string;
date?: never;
timeRemaining?: never;
};

export type CardProps = RemindProps | BookmarkDefaultProps | BookmarkSaveProps;

const Card = (
props: CardProps & {
Expand Down
45 changes: 32 additions & 13 deletions packages/design-system/src/components/card/MyBookmarkCard.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import chippiNoImage from '../../assets/chippi_no_image.svg';
import { Icon } from '../../icons';
import Chip, { ChipColor } from '../chip/Chip';

import BaseCard from './BaseCard';

interface MyBookmarkCardProps {
Expand All @@ -9,7 +10,9 @@ interface MyBookmarkCardProps {
category?: string;
categoryColor?: string;
imageUrl?: string;
date: string;
variant?: 'default' | 'save';
date?: string;
nickname?: string;
onClick?: () => void;
onOptionsClick?: (e: React.MouseEvent<HTMLButtonElement>) => void;
}
Expand All @@ -20,10 +23,15 @@ const MyBookmarkCard = ({
category,
categoryColor,
imageUrl,
variant = 'default',
date,
nickname,
onClick,
onOptionsClick,
}: MyBookmarkCardProps) => {
const displayNickname =
nickname && nickname.trim().length > 0 ? nickname : '도토리';

return (
<BaseCard onClick={onClick} className="h-[33.8rem]">
<div className="flex h-[12rem] w-full items-center justify-center overflow-hidden bg-[#F8F8FA]">
Expand All @@ -41,17 +49,19 @@ const MyBookmarkCard = ({
<div className="px-[1.6rem] py-[2.4rem]">
<div className="mb-[0.8rem] flex h-[5.6rem] justify-between gap-[0.8rem]">
<h3 className="head6 line-clamp-2">{title}</h3>
<button
type="button"
aria-label="카테고리 상세"
className="cursor-pointer self-start"
onClick={(e) => {
e.stopPropagation();
onOptionsClick?.(e);
}}
>
<Icon name="ic_details_category" />
</button>
{variant !== 'save' && (
<button
type="button"
aria-label="카테고리 상세"
className="cursor-pointer self-start"
onClick={(e) => {
e.stopPropagation();
onOptionsClick?.(e);
}}
>
<Icon name="ic_details_category" />
</button>
)}
</div>

<p className="body3-r text-font-gray-2 mb-[1.2rem] line-clamp-2 h-[4.2rem]">
Expand All @@ -62,7 +72,16 @@ const MyBookmarkCard = ({
<Chip category={category} color={categoryColor as ChipColor} />
)}

<p className="caption2-m text-font-ltgray-4 mt-[1.2rem]">{date}</p>
{variant === 'save' ? (
<div className="mt-[1.2rem] flex items-center justify-between">
<p className="caption2-m text-font-ltgray-4">
{`(${displayNickname})님의 핀`}
</p>
<Icon name="ic_memo" size={24} className="shrink-0" />
</div>
) : (
<p className="caption2-m text-font-ltgray-4 mt-[1.2rem]">{date}</p>
)}
</div>
</BaseCard>
);
Expand Down
1 change: 1 addition & 0 deletions packages/design-system/src/icons/iconNames.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export const iconNames = [
'ic_details_disable',
'ic_extension',
'ic_info',
'ic_memo',
'ic_pin',
'ic_pin_active',
'ic_pin_disable',
Expand Down
7 changes: 7 additions & 0 deletions packages/design-system/src/icons/source/ic_memo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading