-
Notifications
You must be signed in to change notification settings - Fork 1
Feat(client): 온보딩 페이지 레이아웃 #56
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
5bd7577
404ae5b
624cc17
9a70e01
63d6ffe
af80d54
eddface
e40be82
1969490
8cb98d6
99a5139
70d222e
dc94e2b
ab4b776
ffd5261
5c436c3
0b8eefb
5250c8d
3bb0c7f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| import avatar1 from '@assets/onBoarding/icons/chippi_morning.svg'; | ||
| import avatar2 from '@assets/onBoarding/icons/chippi_night.svg'; | ||
| import avatar3 from '@assets/onBoarding/icons/chippi_bell.svg'; | ||
|
|
||
| export interface AlarmType { | ||
| img: string; | ||
| title: string; | ||
| time: string; | ||
| } | ||
|
|
||
| export const AlarmsType: AlarmType[] = [ | ||
| { img: avatar1, title: '아침형 치삐', time: '오전 9시' }, | ||
| { img: avatar2, title: '저녁형 치삐', time: '오후 8시' }, | ||
| { img: avatar3, title: '사용자 설정', time: '' }, | ||
| ]; | ||
|
Comment on lines
+11
to
+15
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Verification agent 🧩 Analysis chain프리셋은 ‘상태’가 아닙니다: 사용자 선택 값(시간)은 컴포넌트/스토어 상태로 관리하세요 모듈 상수(AlarmsType)를 직접 변경하면 전역 공유로 인해 리렌더/다중 인스턴스/스토리북 병렬 실행 시 예기치 않은 사이드이펙트가 납니다. 프리셋은 불변 상수로 두고, 선택/수정은 로컬 상태(useState)나 전역 스토어(Zustand/Redux 등)로 분리하세요. 다음 명령으로 상수 변이(write) 사용처를 확인해 보세요: 🏁 Script executed: #!/bin/bash
# AlarmsType 요소의 time을 대입(=)하는 코드 탐지
rg -nP 'AlarmsType\s*\[\s*\d+\s*\]\s*\.time\s*=' -C2
rg -nP 'AlarmsType\s*\[\s*.*?\s*\]\s*\.time\s*=' -C2Length of output: 2277 AlarmsType은 불변으로 유지 — 전역 상수 직접 변이 제거하고 사용자 선택은 상태로 관리하세요. apps/client/src/pages/onBoarding/components/funnel/AlarmBox.tsx에서 AlarmsType[2].time에 직접 할당이 발견됩니다 (라인 62: AlarmsType[2].time = formatted, 라인 67: AlarmsType[2].time = ''). 프리셋(AlarmsType)은 불변 상수로 두고, 사용자 선택/수정은 컴포넌트 useState 또는 전역 스토어(Zustand/Redux 등)로 이동해 저장·갱신하세요. 🤖 Prompt for AI Agents |
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,44 @@ | ||||||||||||||||||||||||||||
| import story1 from '@assets/onBoarding/story/story1.svg'; | ||||||||||||||||||||||||||||
| import story2 from '@assets/onBoarding/story/story2.svg'; | ||||||||||||||||||||||||||||
| import story3 from '@assets/onBoarding/story/story3.svg'; | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| export interface Story { | ||||||||||||||||||||||||||||
| img: string; | ||||||||||||||||||||||||||||
| text: React.ReactNode; | ||||||||||||||||||||||||||||
| progress: number; | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
Comment on lines
+5
to
+9
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion
모듈 스코프에서 +import type { ReactNode } from 'react';
export interface Story {
img: string;
- text: React.ReactNode;
+ text: ReactNode;
progress: number;
+ alt: string;
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| export const stories: Story[] = [ | ||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||
| img: story1, | ||||||||||||||||||||||||||||
| text: ( | ||||||||||||||||||||||||||||
| <> | ||||||||||||||||||||||||||||
| 깊고 신비한 숲에는 지식 나무가 있어요. <br /> | ||||||||||||||||||||||||||||
| 지식 나무는 사람들의 잊힌 기록을 도토리 씨앗으로 바꾼답니다. | ||||||||||||||||||||||||||||
| </> | ||||||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||||||
| progress: 30, | ||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||
| img: story2, | ||||||||||||||||||||||||||||
| text: ( | ||||||||||||||||||||||||||||
| <> | ||||||||||||||||||||||||||||
| 당신이 정보를 읽고 활용하는 것을 양분삼아, <br /> | ||||||||||||||||||||||||||||
| 지식 나무에는 맛있는 도토리 열매가 열려요. | ||||||||||||||||||||||||||||
| </> | ||||||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||||||
| progress: 60, | ||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||
| img: story3, | ||||||||||||||||||||||||||||
| text: ( | ||||||||||||||||||||||||||||
| <> | ||||||||||||||||||||||||||||
| 다람쥐 치삐는 정보를 활용하지 못해 아직 도토리 만개 숲에 도착하지 못하고 | ||||||||||||||||||||||||||||
| 있어요. | ||||||||||||||||||||||||||||
| <br /> | ||||||||||||||||||||||||||||
| 도토리를 모아 치삐가 숲에 닿을 수 있도록 도와주세요! | ||||||||||||||||||||||||||||
| </> | ||||||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||||||
| progress: 100, | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| ]; | ||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,16 @@ | ||
| import onBoardingBg from '@assets/onBoarding/background/onBoardingBg.svg'; | ||
| import Header from './components/header/Header'; | ||
| import MainCard from './components/funnel/MainCard'; | ||
| const OnBoarding = () => { | ||
| return <div>OnBoarding</div>; | ||
| return ( | ||
| <div | ||
| className={`relative flex h-screen w-screen items-center justify-center bg-cover bg-center bg-no-repeat`} | ||
| style={{ backgroundImage: `url(${onBoardingBg})` }} | ||
| > | ||
| <Header /> | ||
| <MainCard /> | ||
| </div> | ||
| ); | ||
| }; | ||
|
|
||
| export default OnBoarding; |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,78 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||
| import { cva } from 'class-variance-authority'; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| import TimePicker from '../timePicker/TimePicker'; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| import { AlarmsType } from '@constants/alarms'; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| import { useState } from 'react'; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| interface AlarmBoxProps { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| select: 1 | 2 | 3; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| isDisabled: boolean; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| onClick?: () => void; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| const boxStyle = cva( | ||||||||||||||||||||||||||||||||||||||||||||||||||
| 'flex h-[22.4rem] w-[18rem] flex-col items-center rounded-[1.2rem] px-[3.9rem] pb-[2.6rem] pt-[3.6rem] cursor-pointer transition', | ||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| variants: { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| disabled: { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| true: 'border-main400 bg-main100 border', | ||||||||||||||||||||||||||||||||||||||||||||||||||
| false: 'bg-white border border-transparent hover:border-main300', | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| defaultVariants: { disabled: false }, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+11
to
+22
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion disabled 변형에서도 커서/클릭이 유지됨 베이스 클래스에 -const boxStyle = cva(
- 'flex h-[22.4rem] w-[18rem] flex-col items-center rounded-[1.2rem] px-[3.9rem] pb-[2.6rem] pt-[3.6rem] cursor-pointer transition',
+const boxStyle = cva(
+ 'flex h-[22.4rem] w-[18rem] flex-col items-center rounded-[1.2rem] px-[3.9rem] pb-[2.6rem] pt-[3.6rem] transition',
{
variants: {
disabled: {
- true: 'border-main400 bg-main100 border',
- false: 'bg-white border border-transparent hover:border-main300',
+ true: 'border-main400 bg-main100 border cursor-not-allowed pointer-events-none',
+ false: 'bg-white border border-transparent hover:border-main300 cursor-pointer',
},
},
defaultVariants: { disabled: false },
}
);📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| const AlarmBox = ({ select, isDisabled, onClick }: AlarmBoxProps) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| const [showPicker, setShowPicker] = useState(false); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| const getTimePicker = ({ hour, minute, meridiem }: { hour: string; minute: string; meridiem: string }) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| const formatted = `${meridiem} ${hour}:${minute}`; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| AlarmsType[2].time = formatted; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| setShowPicker(false); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| // 이거 나중에 api 연결때 쓸려고 표시한거.. 그떄 지우겠듬여 console.log('저장된 사용자 알람:', AlarmsType[2].time); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||
| return ( | ||||||||||||||||||||||||||||||||||||||||||||||||||
| <div | ||||||||||||||||||||||||||||||||||||||||||||||||||
| className={boxStyle({ disabled: isDisabled })} | ||||||||||||||||||||||||||||||||||||||||||||||||||
| onClick={() => { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| if (select === 3 && isDisabled) { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| setShowPicker(true); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||
| onClick?.(); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }} | ||||||||||||||||||||||||||||||||||||||||||||||||||
| > | ||||||||||||||||||||||||||||||||||||||||||||||||||
| <img src={AlarmsType[select - 1].img} alt="chippi" /> | ||||||||||||||||||||||||||||||||||||||||||||||||||
| <p | ||||||||||||||||||||||||||||||||||||||||||||||||||
| className={`sub3-sb ${ | ||||||||||||||||||||||||||||||||||||||||||||||||||
| isDisabled ? 'text-main500' : 'text-font-black-1' | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }`} | ||||||||||||||||||||||||||||||||||||||||||||||||||
| > | ||||||||||||||||||||||||||||||||||||||||||||||||||
| {AlarmsType[select - 1].title} | ||||||||||||||||||||||||||||||||||||||||||||||||||
| </p> | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| {select <= 2 && ( | ||||||||||||||||||||||||||||||||||||||||||||||||||
| <p className="caption2-m text-font-gray-3"> | ||||||||||||||||||||||||||||||||||||||||||||||||||
| {AlarmsType[select - 1].time} | ||||||||||||||||||||||||||||||||||||||||||||||||||
| </p> | ||||||||||||||||||||||||||||||||||||||||||||||||||
| )} | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| {select === 3 && isDisabled && ( | ||||||||||||||||||||||||||||||||||||||||||||||||||
| <> | ||||||||||||||||||||||||||||||||||||||||||||||||||
| {AlarmsType[2].time && ( | ||||||||||||||||||||||||||||||||||||||||||||||||||
| <p className="caption2-m text-font-gray-3">{AlarmsType[2].time}</p> | ||||||||||||||||||||||||||||||||||||||||||||||||||
| )} | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| {showPicker && ( | ||||||||||||||||||||||||||||||||||||||||||||||||||
| <TimePicker | ||||||||||||||||||||||||||||||||||||||||||||||||||
| onSave={getTimePicker} | ||||||||||||||||||||||||||||||||||||||||||||||||||
| onCancel={() => { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| AlarmsType[2].time = ''; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }} | ||||||||||||||||||||||||||||||||||||||||||||||||||
| onClick={(e) => e.stopPropagation()} | ||||||||||||||||||||||||||||||||||||||||||||||||||
| /> | ||||||||||||||||||||||||||||||||||||||||||||||||||
| )} | ||||||||||||||||||||||||||||||||||||||||||||||||||
| </> | ||||||||||||||||||||||||||||||||||||||||||||||||||
| )} | ||||||||||||||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| export default AlarmBox; | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 전체적으로 현재는 |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,137 @@ | ||||||||||||||||||||||||||||||||||||||||||
| import { Progress, Button } from '@pinback/design-system/ui'; | ||||||||||||||||||||||||||||||||||||||||||
| import { useState, useEffect } from 'react'; | ||||||||||||||||||||||||||||||||||||||||||
| import { motion, AnimatePresence } from 'framer-motion'; | ||||||||||||||||||||||||||||||||||||||||||
| import StoryStep from './step/StoryStep'; | ||||||||||||||||||||||||||||||||||||||||||
| import AlarmStep from './step/AlarmStep'; | ||||||||||||||||||||||||||||||||||||||||||
| import MacStep from './step/MacStep'; | ||||||||||||||||||||||||||||||||||||||||||
| import FinalStep from './step/FinalStep'; | ||||||||||||||||||||||||||||||||||||||||||
| import { cva } from 'class-variance-authority'; | ||||||||||||||||||||||||||||||||||||||||||
| const stepProgress = [{ progress: 30 }, { progress: 60 }, { progress: 100 }]; | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| const variants = { | ||||||||||||||||||||||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. slideIn~Out 느낌으로 네이밍 구체화 했습니당 |
||||||||||||||||||||||||||||||||||||||||||
| slideIn: (direction: number) => ({ | ||||||||||||||||||||||||||||||||||||||||||
| x: direction > 0 ? 200 : -200, | ||||||||||||||||||||||||||||||||||||||||||
| opacity: 0, | ||||||||||||||||||||||||||||||||||||||||||
| }), | ||||||||||||||||||||||||||||||||||||||||||
| slideCenter: { x: 0, opacity: 1 }, | ||||||||||||||||||||||||||||||||||||||||||
| slideOut: (direction: number) => ({ | ||||||||||||||||||||||||||||||||||||||||||
| x: direction > 0 ? -200 : 200, | ||||||||||||||||||||||||||||||||||||||||||
| opacity: 0, | ||||||||||||||||||||||||||||||||||||||||||
| }), | ||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||
| const CardStyle = cva( | ||||||||||||||||||||||||||||||||||||||||||
| 'bg-white-bg flex h-[54.8rem] w-[63.2rem] flex-col items-center justify-between rounded-[2.4rem] pt-[3.2rem]', | ||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||
| variants: { | ||||||||||||||||||||||||||||||||||||||||||
| overflow: { | ||||||||||||||||||||||||||||||||||||||||||
| true: 'overflow-visible', | ||||||||||||||||||||||||||||||||||||||||||
| false: 'overflow-hidden', | ||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||
| defaultVariants: { overflow: false }, | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||
| const MainCard = () => { | ||||||||||||||||||||||||||||||||||||||||||
| const [step, setStep] = useState(0); | ||||||||||||||||||||||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 제 개인적인 생각으로는 예를 들어 <Button
variant="primary"
size="medium"
isDisabled={step === 6}
className="ml-auto w-[4.8rem]"
onClick={nextStep}
>이런 코드도 재림님은 이 부분에 대해서 어떻게 생각하시나요!
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 안그래도 구현할때, step 몇이 어떤단계인지 저도 헷갈렸었는데,, 너무 좋은 방향인 것 같아요!! |
||||||||||||||||||||||||||||||||||||||||||
| const [direction, setDirection] = useState(0); | ||||||||||||||||||||||||||||||||||||||||||
| const [alarmSelected, setAlarmSelected] = useState<1 | 2 | 3>(1); | ||||||||||||||||||||||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 1,2,3 보다 더 의미 있는 string 값으로 가독성을 높이는 것은 어떨까요? |
||||||||||||||||||||||||||||||||||||||||||
| const [isMac, setIsMac] = useState(false); | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| useEffect(() => { | ||||||||||||||||||||||||||||||||||||||||||
| const ua = navigator.userAgent.toLowerCase(); | ||||||||||||||||||||||||||||||||||||||||||
| if (ua.includes('mac os') || ua.includes('iphone') || ua.includes('ipad')) { | ||||||||||||||||||||||||||||||||||||||||||
| setIsMac(true); | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| }, []); | ||||||||||||||||||||||||||||||||||||||||||
| const renderStep = () => { | ||||||||||||||||||||||||||||||||||||||||||
| switch (step) { | ||||||||||||||||||||||||||||||||||||||||||
| case 0: | ||||||||||||||||||||||||||||||||||||||||||
| case 1: | ||||||||||||||||||||||||||||||||||||||||||
| case 2: | ||||||||||||||||||||||||||||||||||||||||||
| return <StoryStep step={step as 0 | 1 | 2} />; | ||||||||||||||||||||||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 혹시 스텝꼬일까봐 |
||||||||||||||||||||||||||||||||||||||||||
| case 3: | ||||||||||||||||||||||||||||||||||||||||||
| return <AlarmStep selected={alarmSelected} setSelected={setAlarmSelected} />; | ||||||||||||||||||||||||||||||||||||||||||
| case 4: | ||||||||||||||||||||||||||||||||||||||||||
| if (isMac) return <MacStep />; | ||||||||||||||||||||||||||||||||||||||||||
| return <FinalStep />; | ||||||||||||||||||||||||||||||||||||||||||
| case 5: | ||||||||||||||||||||||||||||||||||||||||||
| if (isMac) return <FinalStep />; | ||||||||||||||||||||||||||||||||||||||||||
| return null; | ||||||||||||||||||||||||||||||||||||||||||
| default: | ||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+56
to
+60
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 비-Apple(Windows 등) 환경에서 step 5가 공백으로 렌더되고, ‘다음’을 두 번 눌러야 홈으로 이동하는 버그 step 5가 @@
- case 5:
- if (isMac) return <FinalStep />;
- return null;
+ case 5:
+ return <FinalStep />;
@@
- const nextStep = () => {
+ const nextStep = () => {
if (step === 3) {
// 이거 이후에 api 붙일 자리 표시임! console.log('선택된 알람:', AlarmsType[alarmSelected - 1].time);
}
- if (step < 5) {
- setDirection(1);
- setStep((prev) => prev + 1);
- } else if (step === 5) {
- window.location.href = '/';
- }
+ const shouldRedirect = (!isMac && step === 4) || (isMac && step === 5);
+ if (shouldRedirect) {
+ window.location.href = '/';
+ return;
+ }
+ setDirection(1);
+ setStep((prev) => prev + 1);
};Also applies to: 65-75 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||
| return <FinalStep />; | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| const nextStep = () => { | ||||||||||||||||||||||||||||||||||||||||||
| if (step === 3) { | ||||||||||||||||||||||||||||||||||||||||||
| // 이거 이후에 api 붙일 자리 표시임! console.log('선택된 알람:', AlarmsType[alarmSelected - 1].time); | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| if (step < 5) { | ||||||||||||||||||||||||||||||||||||||||||
| setDirection(1); | ||||||||||||||||||||||||||||||||||||||||||
| setStep((prev) => prev + 1); | ||||||||||||||||||||||||||||||||||||||||||
| } else if (step === 5) { | ||||||||||||||||||||||||||||||||||||||||||
| window.location.href = '/'; | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| const prevStep = () => { | ||||||||||||||||||||||||||||||||||||||||||
| if (step > 0) { | ||||||||||||||||||||||||||||||||||||||||||
| setDirection(-1); | ||||||||||||||||||||||||||||||||||||||||||
| setStep((prev) => prev - 1); | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+65
to
+82
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. step string 관련 의논을 해보고 필요하다면 로직 관련은 커스텀 훅으로 분리하는 것도 좋을 것 같아요! |
||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| return ( | ||||||||||||||||||||||||||||||||||||||||||
| <div className={CardStyle({ overflow: step === 3 && alarmSelected === 3 })}> | ||||||||||||||||||||||||||||||||||||||||||
| {step < 3 && ( | ||||||||||||||||||||||||||||||||||||||||||
| <Progress | ||||||||||||||||||||||||||||||||||||||||||
| value={stepProgress[step].progress} | ||||||||||||||||||||||||||||||||||||||||||
| variant="profile" | ||||||||||||||||||||||||||||||||||||||||||
| className="w-[15.6rem]" | ||||||||||||||||||||||||||||||||||||||||||
| /> | ||||||||||||||||||||||||||||||||||||||||||
| )} | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| <div className="relative flex h-full w-full items-center justify-center"> | ||||||||||||||||||||||||||||||||||||||||||
| <AnimatePresence custom={direction} mode="wait"> | ||||||||||||||||||||||||||||||||||||||||||
| <motion.div | ||||||||||||||||||||||||||||||||||||||||||
| key={step} | ||||||||||||||||||||||||||||||||||||||||||
| custom={direction} | ||||||||||||||||||||||||||||||||||||||||||
| variants={variants} | ||||||||||||||||||||||||||||||||||||||||||
| initial="slideIn" | ||||||||||||||||||||||||||||||||||||||||||
| animate="slideCenter" | ||||||||||||||||||||||||||||||||||||||||||
| exit="slideOut" | ||||||||||||||||||||||||||||||||||||||||||
| transition={{ duration: 0.4 }} | ||||||||||||||||||||||||||||||||||||||||||
| className="flex h-full flex-col items-center" | ||||||||||||||||||||||||||||||||||||||||||
| > | ||||||||||||||||||||||||||||||||||||||||||
| {renderStep()} | ||||||||||||||||||||||||||||||||||||||||||
| </motion.div> | ||||||||||||||||||||||||||||||||||||||||||
| </AnimatePresence> | ||||||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| <div className="mb-[4.8rem] mt-[1.2rem] flex w-full justify-between px-[3.2rem]"> | ||||||||||||||||||||||||||||||||||||||||||
| {step < 4 && ( | ||||||||||||||||||||||||||||||||||||||||||
| <Button | ||||||||||||||||||||||||||||||||||||||||||
| variant="primary" | ||||||||||||||||||||||||||||||||||||||||||
| size="medium" | ||||||||||||||||||||||||||||||||||||||||||
| isDisabled={step === 0} | ||||||||||||||||||||||||||||||||||||||||||
| className="w-[4.8rem]" | ||||||||||||||||||||||||||||||||||||||||||
| onClick={prevStep} | ||||||||||||||||||||||||||||||||||||||||||
| > | ||||||||||||||||||||||||||||||||||||||||||
| 이전 | ||||||||||||||||||||||||||||||||||||||||||
| </Button> | ||||||||||||||||||||||||||||||||||||||||||
| )} | ||||||||||||||||||||||||||||||||||||||||||
| <Button | ||||||||||||||||||||||||||||||||||||||||||
| variant="primary" | ||||||||||||||||||||||||||||||||||||||||||
| size="medium" | ||||||||||||||||||||||||||||||||||||||||||
| isDisabled={step === 6} | ||||||||||||||||||||||||||||||||||||||||||
| className="ml-auto w-[4.8rem]" | ||||||||||||||||||||||||||||||||||||||||||
| onClick={nextStep} | ||||||||||||||||||||||||||||||||||||||||||
| > | ||||||||||||||||||||||||||||||||||||||||||
| 다음 | ||||||||||||||||||||||||||||||||||||||||||
| </Button> | ||||||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+123
to
+132
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion 다음 버튼 비활성화 조건 버그(step === 6) 수정 step은 0–5 범위로 운용되므로 현재 조건은 영원히 false입니다. 의미 없는 prop 전달이므로 제거하거나 전환 중(isAnimating) 비활성화로 교체하세요. 전환 중 비활성화로 교체 예: - isDisabled={step === 6}
+ isDisabled={isAnimating}단순 제거 예: - isDisabled={step === 6}
+ // isDisabled 제거📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이부분 한번 확인해주세요-! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @jjangminii 네, 확인했습니다! CodeRabbit이 지적한 버그가 맞습니다. 문제점:
수정 방안:
<Button
variant="primary"
size="medium"
className="ml-auto w-[4.8rem]"
onClick={nextStep}
>
다음
</Button>
// 상태 추가
const [isAnimating, setIsAnimating] = useState(false);
// 애니메이션 처리
const nextStep = () => {
setIsAnimating(true);
// ... 기존 로직
setTimeout(() => setIsAnimating(false), 400); // 애니메이션 duration과 맞춤
};
// 버튼에서 사용
<Button
variant="primary"
size="medium"
isDisabled={isAnimating}
className="ml-auto w-[4.8rem]"
onClick={nextStep}
>
다음
</Button>어떤 방향으로 수정하실 건가요? |
||||||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| export default MainCard; | ||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| import dotori from '@assets/onBoarding/icons/dotori.svg'; | ||
| import AlarmBox from '../AlarmBox'; | ||
| interface AlarmStepProps { | ||
| selected: 1 | 2 | 3; | ||
| setSelected: (n: 1 | 2 | 3) => void; | ||
| } | ||
| const AlarmStep = ({ selected, setSelected }: AlarmStepProps) => { | ||
| return ( | ||
| <div className="flex flex-col items-center justify-between"> | ||
| <img src={dotori} className="mb-[1.2rem]" alt="dotori" /> | ||
| <p className="head2 text-font-black-1"> | ||
| 도토리 찾으러 갈 시간을 정해볼까요? | ||
| </p> | ||
| <p className="body2-m text-font-gray-3 mb-[4.3rem] mt-[0.8rem] text-center"> | ||
| 매일 지정한 시간에 저장한 북마크를 리마인드해드려요 | ||
| </p> | ||
|
|
||
| <div className="mb-[2rem] flex w-full items-center justify-center gap-[1.4rem]"> | ||
| {([1, 2, 3] as const).map((n) => ( | ||
| <AlarmBox | ||
| key={n} | ||
| select={n} | ||
| isDisabled={selected === n} | ||
| onClick={() => setSelected(n)} | ||
| /> | ||
| ))} | ||
| </div> | ||
| </div> | ||
| ); | ||
| }; | ||
|
|
||
| export default AlarmStep; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| import dotori from '@assets/onBoarding/icons/dotori.svg'; | ||
| const FinalStep = () => { | ||
| return ( | ||
| <div className="flex h-full flex-col items-center"> | ||
| <img src={dotori} className="mb-[1.2rem]" alt="dotori" /> | ||
| <p className="head2 text-font-black-1"> | ||
| 도토리 찾으러 갈 시간을 정해볼까요? | ||
| </p> | ||
| </div> | ||
| ); | ||
| }; | ||
| export default FinalStep; |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,17 @@ | ||||||
| import MacNotice from '@assets/onBoarding/story/macNotice.svg'; | ||||||
| import dotori from '@assets/onBoarding/icons/dotori.svg'; | ||||||
| const MacStep = () => { | ||||||
| return ( | ||||||
| <div className="flex h-full flex-col items-center"> | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion 절대 위치 요소가 기준 요소 없이 배치됩니다 — 컨테이너에 하단 이미지가 다음으로 수정해 주세요: - <div className="flex h-full flex-col items-center">
+ <div className="relative flex h-full flex-col items-center">📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||
| <img src={dotori} className="mb-[1.2rem]" alt="dotori" /> | ||||||
| <p className="head2 text-font-black-1"> | ||||||
| 도토리 찾으러 갈 시간을 정해볼까요? | ||||||
| </p> | ||||||
| <p className="body2-m text-font-gray-3 mb-[4.3rem] mt-[0.8rem] text-center"> | ||||||
| Mac 사용자는 추가 알림 설정을 진행해 주세요. | ||||||
| </p> | ||||||
| <img src={MacNotice} className="absolute -bottom-[10.4rem]" alt="mac" /> | ||||||
| </div> | ||||||
| ); | ||||||
| }; | ||||||
| export default MacStep; | ||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| import { stories } from '@constants/stories'; | ||
|
|
||
| interface StoryStepProps { | ||
| step: 0 | 1 | 2; | ||
| } | ||
|
|
||
| const StoryStep = ({ step }: StoryStepProps) => { | ||
| const story = stories[step]; | ||
|
|
||
| return ( | ||
| <div className="flex flex-col items-center"> | ||
| <img | ||
| src={story.img} | ||
| className="mb-[1.6rem] mt-[2.4rem] w-[31.2rem]" | ||
| alt="onboarding" | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| /> | ||
| <p className="sub4-sb text-center text-black">{story.text}</p> | ||
| </div> | ||
| ); | ||
| }; | ||
|
|
||
| export default StoryStep; | ||

There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
상수(프리셋) 변이 방지: 필드를 readonly로 고정하세요
컴포넌트에서
AlarmsType[2].time = ...와 같이 변경 시도가 보입니다. 타입 레벨에서 변이를 차단하면 의도치 않은 전역 상태 오염을 예방할 수 있습니다.📝 Committable suggestion
🤖 Prompt for AI Agents