Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
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: 1 addition & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,7 @@
"tailwind-merge": "^3.3.1",
"vite-plugin-svgr": "^4.3.0",
"zustand": "^5.0.6"


},

},
"devDependencies": {
"@eslint/js": "^9.29.0",
"@svgr/cli": "^8.1.0",
Expand Down
14 changes: 7 additions & 7 deletions src/components/common/ToggleTab/ToggleTab.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import type { ToggleTabProps } from './ToggleTab.types';

const ToggleTab = ({ options, selected, onSelect }: ToggleTabProps) => {
const selectedIndex = options.findIndex((option) => option === selected);
const selectedIndex = options.findIndex((option) => option.value === selected);

return (
<div className="relative flex flex-col gap-5 p-4 bg-transparent w-full">
<div className="relative flex w-full max-w-[335px] h-12 bg-[rgba(66,66,66,0.3)] rounded-[12px] px-1 py-1 gap-[10px]">
<div className="relative flex flex-col gap-5 bg-transparent w-full">
<div className="relative flex w-full h-12 bg-[rgba(66,66,66,0.3)] rounded-[12px] px-1 py-1">
{/* Slider */}
<div
className="absolute top-2 h-[calc(100%-16px)] w-[calc(50%-14px)] border-[1.5px] border-gray-500 rounded-[8px] transition-all duration-300 z-10"
Expand All @@ -17,13 +17,13 @@ const ToggleTab = ({ options, selected, onSelect }: ToggleTabProps) => {
{/* Buttons */}
{options.map((option) => (
<button
key={option}
onClick={() => onSelect(option)}
key={option.value}
onClick={() => onSelect(option.value)}
className={`flex-1 z-20 text-body-1 py-[10px] transition-colors duration-200 whitespace-nowrap overflow-hidden text-ellipsis ${
option === selected ? 'text-[#E0E0E0]' : 'text-[#616161]'
option.value === selected ? 'text-[#E0E0E0]' : 'text-[#616161]'
}`}
>
{option}
{option.label}
</button>
))}
</div>
Expand Down
8 changes: 7 additions & 1 deletion src/components/common/ToggleTab/ToggleTab.types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
export interface ToggleOption {
label: string;
value: string;
}

export interface ToggleTabProps {
options: string[];
options: ToggleOption[];
selected: string;
onSelect: (option: string) => void;
className?: string;
}
1 change: 1 addition & 0 deletions src/components/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ import Badge from '@/components/common/Badge/Badge';
import Image from '@/components/common/Image/Image';
import ToggleTab from '@/components/common/ToggleTab';


export { Button, ToggleTab, Badge, Image, BottomNavigation, BestCinemaCard, ReviewCard };
102 changes: 78 additions & 24 deletions src/pages/onboarding/OnboardingGenrePage.tsx
Original file line number Diff line number Diff line change
@@ -1,40 +1,94 @@
import { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import ToggleTab from '@/components/common/ToggleTab/ToggleTab';
import { useOnboardingStore } from '@/store/useOnboardingStore';
import Header from '@/components/common/Header/Header';
import Button from '@/components/common/Button';
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

여기는 import {Header, Button} from '@/components' 이런식으로 더 간단하게 쓰실 수 있습니다!

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

넵! 통일된 구조로 수정했습니다.

import type { GenreType } from '@/types/onboarding';

const genreOptions: GenreType[] = ['액션', '로맨스'];
const genreOptions = [
'액션', '호러', '스릴러', '코미디',
'SF', '로맨스', '판타지', '미스터리',
'범죄', '모험', '전쟁', '역사',
'뮤지컬', '애니메이션', '드라마',
] as GenreType[];
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

이것도 types폴더로 분리해주시는게 깔끔할 것 같습니당~

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

types 폴더로 각각 분리해서 관리하도록 수정 완료했습니다~! 말씀 감사합니다 🙏


const OnboardingGenrePage = () => {
const navigate = useNavigate();
const { setGenre } = useOnboardingStore();
const [selectedGenre, setSelectedGenre] = useState<GenreType | ''>('');
const [selectedGenres, setSelectedGenres] = useState<GenreType[]>([]);

const handleNext = () => {
if (!selectedGenre) {
alert('하나 이상의 장르를 선택해주세요!');
return;
const toggleGenre = (genre: GenreType) => {
const isSelected = selectedGenres.includes(genre);
if (isSelected) {
setSelectedGenres(selectedGenres.filter((g) => g !== genre));
} else {
if (selectedGenres.length >= 5) return;
setSelectedGenres([...selectedGenres, genre]);
}
};

setGenre([selectedGenre]);
navigate('/signup/onboarding/theater');
const handleBack = () => {
navigate(-1);
};

const handleNext = () => {
if (selectedGenres.length === 0) return;
navigate('/onboarding/theater');
};

return (
<div className="flex flex-col gap-8 items-center justify-center w-full h-screen px-6 py-8">
<ToggleTab
options={genreOptions}
selected={selectedGenre}
onSelect={(genre) => setSelectedGenre(genre as GenreType)} // optional
/>

<button
onClick={handleNext}
className="bg-white text-black hover:opacity-90 w-full max-w-sm"
>
다음
</button>
<div className="min-h-screen bg-gray-900 text-white w-full max-w-[375px] mx-auto relative pb-32">
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

말씀드렸듯이, 이 부분에서도 배경색, 너비, 높이 관련 속성은 제거해주셔도 괜찮을 것 같아요~~

{/* 상단 헤더 */}
<Header title="" onBackClick={handleBack} />
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

제 PR에서 헤더 공통 컴포넌트를 수정해두어서 아이콘을 선택적으로 지우실 수 있게 해뒀습니다!
pull 하신 다음에 showLike={false} showBookmark={false} 추가하시면 헤더에서 아이콘이 보이지 않을거예요 👍👍

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

확인했습니다! showLike, showBookmark props 덕분에 아이콘 잘 제거했습니다 :)


{/* 진행도 바 */}
<div className="mt-6 mb-2">
<div className="h-2 w-full bg-gray-800 relative">
<div className="absolute left-0 top-0 h-full bg-red-400" style={{ width: '66.66%' }} />
</div>
</div>

{/* 콘텐츠 영역 */}
<div className="px-6 mt-6">
{/* 진행도 */}
<div className="text-title-1 text-white mb-3">2/3</div>

{/* 타이틀 */}
<h1 className="text-title-2 text-white mb-1">좋아하는 장르를 선택해주세요</h1>
<p className="text-caption-2 text-red-300 mb-6">최대 5개까지 추가할 수 있어요.</p>

{/* 장르 선택 버튼 */}
<div className="flex flex-wrap gap-3 mb-20">
{genreOptions.map((genre) => {
const isSelected = selectedGenres.includes(genre);
return (
<Button
key={genre}
variant="secondary-assistive"
selected={isSelected}
onClick={() => toggleGenre(genre)}
fontType="body-1"
className="px-4 py-1"
>
{genre}
</Button>
);
})}
</div>
</div>

{/* 하단 버튼 */}
<div className="fixed bottom-8 left-1/2 -translate-x-1/2 w-full max-w-[375px] px-6">
<Button
onClick={handleNext}
disabled={selectedGenres.length === 0}
variant="primary"
color="red"
size="lg"
fontType="title-3"
className="w-full"
>
다음
</Button>
</div>
</div>
);
};
Expand Down
95 changes: 65 additions & 30 deletions src/pages/onboarding/OnboardingNicknamePage.tsx
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

온보딩 페이지에서 공통되는 속성들이 많은데 지민님이 올려주신 pr #23 에 제가 남겼던 리뷰 참고해서 라우팅 방식을 수정하는 것도 좋을 것 같다는 생각이 듭니다~~ 참고해주시면 좋을 것 같아요~

Original file line number Diff line number Diff line change
@@ -1,43 +1,78 @@
import { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { useOnboardingStore } from '@/store/useOnboardingStore';
import { Button } from '@/components';
import Input from '@/components/common/Input/Input';
import Header from '@/components/common/Header/Header';
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

여기도 마찬가지로 import {Button, Input, Header} from '@/components' 이런 식으로 써주시면 코드가 더 깔끔해질 것 같습니다👍👍

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

이 부분도 동일하게 반영했어요! 감사합니다


const OnboardingNicknamePage = () => {
const [nickname, setNickname] = useState('');
const { setNickname: saveNickname } = useOnboardingStore();
const [input, setInput] = useState('');
const navigate = useNavigate();

const handleNext = () => {
if (!nickname.trim()) return;
saveNickname(nickname);
navigate('/signup/genre'); // 다음 단계로 이동
console.log('닉네임:', input);
navigate('/onboarding/genre');
};

const handleBack = () => {
navigate(-1);
};

return (
<div className="h-screen bg-[#121212] text-white flex flex-col items-center px-6 pt-20">
<p className="text-[#E31221] text-sm mb-2">1/3</p>
<h1 className="text-xl font-semibold mb-2">닉네임을 입력해주세요</h1>
<p className="text-sm text-gray-400 mb-8">다른 유저에게 보여질 이름이에요</p>

<input
type="text"
value={nickname}
onChange={(e) => setNickname(e.target.value)}
placeholder="닉네임을 입력하세요"
className="w-full max-w-sm px-4 py-3 rounded-md bg-[#1E1E1E] text-white border border-gray-600 placeholder-gray-500 focus:outline-none mb-6"
/>

<button
onClick={handleNext}
disabled={!nickname.trim()}
className={`w-full max-w-sm py-3 rounded-md font-semibold ${
nickname.trim()
? 'bg-[#E31221] text-white'
: 'bg-gray-600 text-gray-400 cursor-not-allowed'
}`}
>
다음
</button>
<div className="min-h-screen w-full max-w-[375px] mx-auto bg-gray-900 text-white relative pb-32">
{/* 상단 헤더 */}
<Header title="" onBackClick={handleBack} />

{/* 진행도 바 */}
<div className="mt-6 mb-2">
<div className="h-2 w-full bg-gray-800 relative">
<div className="absolute left-0 top-0 h-full bg-red-400" style={{ width: '33.33%' }} />
</div>
</div>
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

진행도 바를 현재 방식처럼 보여주는 것도 간단하고 나쁘지 않다고 생각하지만,
진행바를 컴포넌트로 분리해서 currentStep과 totalSteps를 props로 받아서 width를 계산하도로 하는게 재사용성과 유지보수 측면에서 더 좋을 것 같은데 세렴님 의견은 어떠신가용??

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

말씀해주신 대로 수정하는게 관리하기에 더 좋을 것 같아서, 진행도 바를 currentStep, totalSteps prop 기반으로 분리했고, 진행 텍스트(1/3, 2/3 등)도 함께 컴포넌트 내부로 이동해서 통합 관리하도록 했습니다!


{/* 콘텐츠 영역 */}
<div className="px-6 mt-6">
{/* 진행도 */}
<div className="text-title-1 text-white mb-3">1/3</div>
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

추가로, 1/3, 2/3, 3/3과 같은 텍스트도
진행도 바 컴포넌트 안에서

<div className="text-title-1 text-white mb-3">
  {currentStep}/{totalSteps}
</div>

처럼 함께 관리하면 더 일관성 있게 관리할 수 있을 것 같아요~!


{/* 타이틀 */}
<h1 className="text-title-2 mb-10">프로필을 만들어주세요</h1>

{/* 프로필 이미지 (예시용 박스) */}
<div className="flex justify-center mb-10">
<div className="w-36 h-36 rounded-full bg-gray-100 flex items-center justify-center text-black text-sm">
갤러리 아이콘
</div>
</div>

{/* 닉네임 입력 */}
<div className="mb-2">
<Input
label=""
value={input}
onChange={setInput}
placeholder="닉네임을 입력해주세요"
placeholderColorType="gray"
showBackground={true}
/>
</div>
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Input 컴포넌트도 제가 onClickPlus prop을 전달받지 않으면 + 버튼 랜더링 되지 않도록 수정해두었습니다! pull하신 후에 잘 적용되는지 한 번 확인해주세요 🙌🙌


<p className="text-caption-3 text-gray-500 ml-1">10자 이내로 작성해주세요.</p>
</div>

{/* 하단 버튼 */}
<div className="fixed bottom-8 left-1/2 -translate-x-1/2 w-full max-w-[375px] px-6">
<Button
onClick={handleNext}
disabled={!input.trim()}
variant="primary"
color="red"
size="lg"
fontType="title-3"
className="w-full"
>
다음
</Button>
</div>
</div>
);
};
Expand Down
Loading