Skip to content

Commit

Permalink
fix(bottle, e2e): change create profile page url
Browse files Browse the repository at this point in the history
  • Loading branch information
stakbucks committed Sep 15, 2024
1 parent 797696f commit 8ffd316
Show file tree
Hide file tree
Showing 33 changed files with 1,256 additions and 60 deletions.
10 changes: 10 additions & 0 deletions apps/bottle/src/app/profile/create/CreateProfileProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
'use client';

import { createFunnelValuesContext } from '@/features/funnel-values/createFunnelValuesContext';
import { Profile } from '@/models/profile';

export interface CreateProfileValues extends Profile {
kakaoId: string;
}

export const [CreateProfileProvider, useCreateProfileValues] = createFunnelValuesContext<CreateProfileValues>();
13 changes: 13 additions & 0 deletions apps/bottle/src/app/profile/create/SignupProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
'use client';

import { createFunnelValuesContext } from '@/features/funnel-values/createFunnelValuesContext';

export interface SignupProfileValues {
birthDay: number;
birthMonth: number;
birthYear: number;
gender: 'MALE' | 'FEMALE';
name: string;
}

export const [SignupProfileProvider, useSignupProfileValues] = createFunnelValuesContext<SignupProfileValues>();
40 changes: 40 additions & 0 deletions apps/bottle/src/app/profile/create/_steps/MBTI/MBTI.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { StepProvider } from '@/features/steps/StepProvider';
import { userInfoQueryOptions } from '@/store/query/useUserInfoQuery';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { render } from '@testing-library/react';
import { CreateProfileProvider } from '../../CreateProfileProvider';
import { MBTI } from '.';

vi.mock('next/navigation', () => ({
useSearchParams: () => ({ get: vi.fn() }),
useRouter: () => ({ push: vi.fn() }),
}));

it('sets previous selected MBTI to initial state for each mbti selections', async () => {
const testClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: Infinity,
gcTime: Infinity,
},
},
});
testClient.setQueryData(userInfoQueryOptions({ accessToken: '', refreshToken: '' }).queryKey, { name: 'taehwan' });

const MBTIRender = () => (
<QueryClientProvider client={testClient}>
<CreateProfileProvider initial={{ mbti: 'ESFJ' }}>
<StepProvider maxStep={9} uri={'/test'}>
<MBTI />
</StepProvider>
</CreateProfileProvider>
</QueryClientProvider>
);

const screen = render(<MBTIRender />);
const EButton = screen.getByText('E');
const nextButton = screen.getByText('다음');

expect(EButton).toHaveAttribute('aria-selected', 'true');
expect(nextButton).not.toBeDisabled();
});
26 changes: 26 additions & 0 deletions apps/bottle/src/app/profile/create/_steps/MBTI/MBTIStyle.css.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { spacings } from '@bottlesteam/ui';
import { style } from '@vanilla-extract/css';

export const bodyStyle = style({
marginTop: spacings.xxl,
display: 'flex',
flexDirection: 'column',
gap: spacings.xl,
paddingBottom: spacings.xxl,
});

export const controlStyle = style({
display: 'flex',
flexDirection: 'column',
gap: spacings.sm,
});

export const buttonsContainerStyle = style({
display: 'flex',
width: '100%',
gap: spacings.sm,
});

export const spacingStyle = style({
height: spacings.sm,
});
106 changes: 106 additions & 0 deletions apps/bottle/src/app/profile/create/_steps/MBTI/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { Control, toggle } from '@/components/control';
import { Step } from '@/features/steps/StepContainer';
import { useStep } from '@/features/steps/StepProvider';
import { EIType, JPType, SNType, TFType } from '@/models/profile/MBTI';
import { useUserInfoQuery } from '@/store/query/useUserInfoQuery';
import { Button, ButtonProps } from '@bottlesteam/ui';
import { useMemo, useState } from 'react';
import { useCreateProfileValues } from '../../CreateProfileProvider';
import { bodyStyle, buttonsContainerStyle, controlStyle } from './MBTIStyle.css';

export function MBTI() {
const { onNextStep } = useStep();
const { setValue, getValue } = useCreateProfileValues();
const {
data: { name },
} = useUserInfoQuery();

const selected = getValue('mbti');

const [EI, setEI] = useState<EIType | undefined>(() => (selected != null ? (selected[0] as EIType) : undefined));
const [SN, setSN] = useState<SNType | undefined>(selected != null ? (selected[1] as SNType) : undefined);
const [TF, setTF] = useState<TFType | undefined>(selected != null ? (selected[2] as TFType) : undefined);
const [JP, setJP] = useState<JPType | undefined>(selected != null ? (selected[3] as JPType) : undefined);

const isDisabled = useMemo(() => EI == null || SN == null || TF == null || JP == null, [EI, JP, TF, SN]);

return (
<>
<Step.Title>{name}님의 성격에 대해 알고 싶어요</Step.Title>
<section className={bodyStyle}>
<div className={controlStyle}>
<Step.Subtitle>외향형 · 내향형</Step.Subtitle>
<div className={buttonsContainerStyle}>
<Control value={EI}>
<Control.Item value={'E'} onClick={() => setEI(prev => toggle(prev, 'E'))}>
<ItemButton aria-selected={EI === 'E'}>E</ItemButton>
</Control.Item>
<Control.Item value={'I'} onClick={() => setEI(prev => toggle(prev, 'I'))}>
<ItemButton aria-selected={EI === 'I'}>I</ItemButton>
</Control.Item>
</Control>
</div>
</div>
<div className={controlStyle}>
<Step.Subtitle>감각형 · 직관형</Step.Subtitle>
<div className={buttonsContainerStyle}>
<Control value={SN}>
<Control.Item value={'S'} onClick={() => setSN(prev => toggle(prev, 'S'))}>
<ItemButton aria-selected={SN === 'S'}>S</ItemButton>
</Control.Item>
<Control.Item value={'N'} onClick={() => setSN(prev => toggle(prev, 'N'))}>
<ItemButton aria-selected={SN === 'N'}>N</ItemButton>
</Control.Item>
</Control>
</div>
</div>
<div className={controlStyle}>
<Step.Subtitle>사고형 · 감정형</Step.Subtitle>
<div className={buttonsContainerStyle}>
<Control value={TF}>
<Control.Item value={'T'} onClick={() => setTF(prev => toggle(prev, 'T'))}>
<ItemButton aria-selected={TF === 'T'}>T</ItemButton>
</Control.Item>
<Control.Item value={'F'} onClick={() => setTF(prev => toggle(prev, 'F'))}>
<ItemButton aria-selected={TF === 'F'}>F</ItemButton>
</Control.Item>
</Control>
</div>
</div>
<div className={controlStyle}>
<Step.Subtitle>판단형 · 인식형</Step.Subtitle>
<div className={buttonsContainerStyle}>
<Control value={JP}>
<Control.Item value={'J'} onClick={() => setJP(prev => toggle(prev, 'J'))}>
<ItemButton aria-selected={JP === 'J'}>J</ItemButton>
</Control.Item>
<Control.Item value={'P'} onClick={() => setJP(prev => toggle(prev, 'P'))}>
<ItemButton aria-selected={JP === 'P'}>P</ItemButton>
</Control.Item>
</Control>
</div>
</div>
</section>
<Step.FixedButton
disabled={isDisabled}
onClick={() => {
if (EI == null || SN == null || TF == null || JP == null) {
return;
}
setValue('mbti', `${EI}${SN}${TF}${JP}`);
onNextStep();
}}
>
다음
</Step.FixedButton>
</>
);
}

function ItemButton(props: Omit<ButtonProps, 'variant' | 'size'>) {
return (
<Button variant="outlined" size="md" selected={props.selected} style={{ flex: 1 }} {...props}>
{props.children}
</Button>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { spacings } from '@bottlesteam/ui';
import { style } from '@vanilla-extract/css';

export const alcoholStyle = style({
marginTop: spacings.xxl,
display: 'flex',
flexDirection: 'column',
gap: spacings.sm,
});
44 changes: 44 additions & 0 deletions apps/bottle/src/app/profile/create/_steps/alcohol/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { Control, toggle } from '@/components/control';
import { Step } from '@/features/steps/StepContainer';
import { useStep } from '@/features/steps/StepProvider';
import { Alcohol as AlcoholType, alcoholList } from '@/models/profile/alcohol';
import { Button } from '@bottlesteam/ui';
import { useState } from 'react';
import { useCreateProfileValues } from '../../CreateProfileProvider';
import { alcoholStyle } from './alcoholStyle.css';

export function Alcohol() {
const { setValue, getValue } = useCreateProfileValues();
const { onNextStep } = useStep();

const [alcohol, setAlcohol] = useState<AlcoholType | undefined>(getValue('alcohol'));

return (
<>
<Step.Title>술은 얼마나 즐기나요?</Step.Title>
<Control value={alcohol}>
<section className={alcoholStyle}>
{alcoholList.map((item, index) => (
<Control.Item key={index} value={item} onClick={() => setAlcohol(prev => toggle(prev, item))}>
<Button variant="outlined" size="md" style={{ width: '100%' }}>
{item}
</Button>
</Control.Item>
))}
</section>
</Control>
<Step.FixedButton
disabled={alcohol === undefined}
onClick={() => {
if (alcohol === undefined) {
throw new Error();
}
setValue('alcohol', alcohol);
onNextStep();
}}
>
다음
</Step.FixedButton>
</>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { spacings } from '@bottlesteam/ui';
import { style } from '@vanilla-extract/css';

export const wheelPickerContainerStyle = style({
width: '100%',
marginTop: spacings.xxl,
});
51 changes: 51 additions & 0 deletions apps/bottle/src/app/profile/create/_steps/height/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
'use client';

import { Step } from '@/features/steps/StepContainer';
import { useStep } from '@/features/steps/StepProvider';
import { WheelPicker, colors } from '@bottlesteam/ui';
import { useState } from 'react';
import { useCreateProfileValues } from '../../CreateProfileProvider';
import { wheelPickerContainerStyle } from './heightStyle.css';

const OFFSET = 140;
const DEFAULT_ID = '168';

const heightData = Array.from({ length: 61 }, (_, index) => ({
id: `${index + OFFSET}`,
value: `${index + OFFSET}cm`,
}));

export function Height() {
const { setValue, getValue } = useCreateProfileValues();
const { onNextStep } = useStep();

const [height, setHeight] = useState(getValue('height') ?? Number(DEFAULT_ID));

return (
<>
<Step.Title>키는 어떻게 되나요?</Step.Title>
<div className={wheelPickerContainerStyle}>
<WheelPicker
data={heightData}
onChange={({ id }) => setHeight(Number(id))}
selectedID={String(height)}
fontSize={14}
height={250}
width={'100%'}
itemHeight={56}
shadowColor="none"
activeColor={colors.neutral900}
color={colors.neutral600}
/>
</div>
<Step.FixedButton
onClick={() => {
setValue('height', height);
onNextStep();
}}
>
다음
</Step.FixedButton>
</>
);
}
Loading

0 comments on commit 8ffd316

Please sign in to comment.