Skip to content
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

feat(bottle, ui): user self introduction #63

Merged
merged 11 commits into from
Sep 28, 2024
8 changes: 4 additions & 4 deletions apps/bottle/src/app/admin/login/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { Header } from '@/components/common/header';
import { POST } from '@/features/server';
import { Step } from '@/features/steps/StepContainer';
import { spacings, TextField } from '@bottlesteam/ui';
import { spacings, Input } from '@bottlesteam/ui';
import { setCookie } from 'cookies-next';
import { useRouter } from 'next/navigation';
import { useState } from 'react';
Expand Down Expand Up @@ -57,7 +57,7 @@ export default function LoginPage() {
<section className={containerStyle}>
<div className={fieldStyle}>
<Step.Subtitle>아이디</Step.Subtitle>
<TextField
<Input
value={id}
placeholder="아이디를 입력해 주세요"
onChange={e => {
Expand All @@ -67,14 +67,14 @@ export default function LoginPage() {
</div>
<div className={fieldStyle}>
<Step.Subtitle>비밀번호</Step.Subtitle>
<TextField
<Input
value={password}
onChange={e => {
setPassword(e.currentTarget.value);
}}
type="password"
placeholder="비밀번호를 입력해 주세요"
caption={isError && <TextField.Caption>{ERROR_MESSAGE}</TextField.Caption>}
caption={isError && <Input.Caption>{ERROR_MESSAGE}</Input.Caption>}
/>
</div>
</section>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Control } from '@/components/common/control';
import { Asset, BottomSheet, BottomSheetProps, Button, Paragraph, TextField, spacings } from '@bottlesteam/ui';
import { Asset, BottomSheet, BottomSheetProps, Button, Paragraph, Input, spacings } from '@bottlesteam/ui';
import { useEffect, useState } from 'react';
import { deleteButtonStyle, emoticonsContainer } from './bottomSheetStyle.css';

Expand Down Expand Up @@ -32,7 +32,7 @@ export function ExpressInterestBottomSheet({ onExpress, ...bottomSheetProps }: P
size="sm"
body={
<>
<TextField
<Input
placeholder="호감이 생긴 이유를 적어보세요"
value={message}
onChange={e => setMessage(e.currentTarget.value)}
Expand All @@ -50,7 +50,7 @@ export function ExpressInterestBottomSheet({ onExpress, ...bottomSheetProps }: P
)
}
/>
<TextField.Caption>{isError && ERROR_CAPTION}</TextField.Caption>
<Input.Caption>{isError && ERROR_CAPTION}</Input.Caption>
<Paragraph typography="st2" color="neutral600" style={{ marginTop: spacings.xl }}>
이모티콘으로 표현해보세요
</Paragraph>
Expand Down
10 changes: 5 additions & 5 deletions apps/bottle/src/app/create-profile/_steps/information/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Control } from '@/components/common/control';
import { Step } from '@/features/steps/StepContainer';
import { useStep } from '@/features/steps/StepProvider';
import { useSignupProfileMutation } from '@/store/mutation/useSignupProfileMutation';
import { Button, TextField } from '@bottlesteam/ui';
import { Button, Input } from '@bottlesteam/ui';
import { useState } from 'react';
import { useSignupProfileValues, SignupProfileValues } from '../../SignupProvider';
import { birthDateWrapper, buttonsWrapper, containerStyle, fieldStyle } from './informationStyle.css';
Expand Down Expand Up @@ -37,28 +37,28 @@ export function Information() {
<Step.Subtitle asChild>
<label>이름</label>
</Step.Subtitle>
<TextField placeholder="홍길동" value={name} onChange={e => setName(e.currentTarget.value)} />
<Input placeholder="홍길동" value={name} onChange={e => setName(e.currentTarget.value)} />
</div>
<div className={fieldStyle}>
<Step.Subtitle asChild>
<label>생년월일</label>
</Step.Subtitle>
<div className={birthDateWrapper}>
<TextField
<Input
placeholder="YYYY"
type="number"
maxLength={4}
value={year}
onChange={e => setYear(e.currentTarget.value)}
/>
<TextField
<Input
placeholder="MM"
type="number"
value={month}
maxLength={2}
onChange={e => setMonth(e.currentTarget.value)}
/>
<TextField
<Input
placeholder="DD"
type="number"
value={day}
Expand Down
6 changes: 3 additions & 3 deletions apps/bottle/src/app/create-profile/_steps/kakao-id/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { AppBridgeMessageType, useAppBridge } from '@/features/app-bridge';
import { POST, createInit } from '@/features/server';
import { getClientSideTokens } from '@/features/server/clientSideTokens';
import { Step } from '@/features/steps/StepContainer';
import { TextField, spacings } from '@bottlesteam/ui';
import { Input, spacings } from '@bottlesteam/ui';
import { useState } from 'react';
import { useCreateProfileValues } from '../../CreateProfileProvider';

Expand All @@ -21,13 +21,13 @@ export function KaKaoId() {
<>
<Step.Title>{'연락처 공유를 위해\n카카오톡 아이디를 입력해 주세요'}</Step.Title>
<Step.Description style={{ marginTop: spacings.sm }}>오타가 없는지 한 번 더 확인해 주세요</Step.Description>
<TextField
<Input
placeholder="영문, 숫자, 특수문자 포함 4-20자"
value={kakaoId}
onChange={e => setKakaoId(e.currentTarget.value)}
style={{ marginTop: spacings.xxl }}
/>
<TextField.Caption>{isError && ERROR_CAPTION}</TextField.Caption>
<Input.Caption>{isError && ERROR_CAPTION}</Input.Caption>
<Step.FixedButton
disabled={disabled}
onClick={async () => {
Expand Down
10 changes: 10 additions & 0 deletions apps/bottle/src/app/intro/create/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { getServerSideTokens } from '@/features/server/serverSideTokens';
import { ServerFetchBoundary } from '@/store/query/ServerFetchBoundary';
import { currentUserProfileQueryOptions } from '@/store/query/useCurrentUserProfileQuery';
import type { ReactNode } from 'react';

export default async function CreateIntroLayout({ children }: { children: ReactNode }) {
const tokens = getServerSideTokens();

return <ServerFetchBoundary fetchOptions={currentUserProfileQueryOptions(tokens)}>{children}</ServerFetchBoundary>;
}
58 changes: 58 additions & 0 deletions apps/bottle/src/app/intro/create/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
'use client';

import { Header } from '@/components/common/header';
import { Stepper } from '@/components/common/stepper';
import { Images } from '@/components/intro/images';
import { Introduction } from '@/components/intro/introduction';
import { ProfileLayout } from '@/components/profile/layout';
import { AppBridgeMessageType, useAppBridge } from '@/features/app-bridge';
import { useFunnel } from '@/features/funnel';
import { Introduction as IntroductionType } from '@/models/introduction';
import { useIntroductionMutation } from '@/store/mutation/useIntroductionMutation';
import { useRouter } from 'next/navigation';

const MAX_STEPS = 2;

type CreateIntroFunnelValues = {
introduction: IntroductionType;
// FIXME: depends on server API
imageUrl: string;
};

export default function CreateIntroPage() {
const { send } = useAppBridge();
const { mutateAsync } = useIntroductionMutation({ type: 'create' });
const router = useRouter();

const { onNextStep, currentStep, getValue } = useFunnel<CreateIntroFunnelValues>('/intro/create');

const steps = [
<ProfileLayout key={1}>
<Header
onGoBack={() => {
send({ type: AppBridgeMessageType.WEB_VIEW_CLOSE });
}}
/>
<Stepper current={1} max={MAX_STEPS} />
<Introduction
initialValue={getValue('introduction')}
onNext={async introduction => {
try {
await mutateAsync(introduction);
onNextStep('introduction', introduction);
} catch (error) {
console.error(error);
}
}}
ctaButtonText="다음"
/>
</ProfileLayout>,
<ProfileLayout key={1}>
<Header onGoBack={router.back} />
<Stepper current={2} max={MAX_STEPS} />
<Images initialValue={getValue('imageUrl')} onNext={() => {}} ctaButtonText="완료" />
</ProfileLayout>,
];

return <>{steps[currentStep - 1]}</>;
}
10 changes: 5 additions & 5 deletions apps/bottle/src/app/login/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { useLeftTimeCaption } from '@/features/time/useLeftTimeCaption';
import { useSendAuthCodeMutation } from '@/store/mutation/useSendAuthCodeMutation';
import { useSignInUpMutation } from '@/store/mutation/useSignInUpMutation';
import { WRONG_AUTH_CODE_MESSAGE } from '@/store/mutation/useSignupMutation';
import { Asset, Button, spacings, TextField } from '@bottlesteam/ui';
import { Asset, Button, spacings, Input } from '@bottlesteam/ui';
import { useState } from 'react';
import { containerStyle, fieldStyle } from './loginStyle.css';

Expand Down Expand Up @@ -50,7 +50,7 @@ export default function LoginPage() {
<section className={containerStyle}>
<div className={fieldStyle}>
<Step.Subtitle>휴대폰 번호</Step.Subtitle>
<TextField
<Input
value={phoneNumber}
maxLength={8}
onChange={e => {
Expand All @@ -67,7 +67,7 @@ export default function LoginPage() {
</div>
<div className={fieldStyle}>
<Step.Subtitle>인증 번호</Step.Subtitle>
<TextField
<Input
value={authCode}
onChange={e => {
setAuthCode(e.currentTarget.value);
Expand All @@ -76,9 +76,9 @@ export default function LoginPage() {
placeholder="번호를 입력해 주세요"
caption={
isAuthCodeError ? (
<TextField.Caption>{WRONG_AUTH_CODE_MESSAGE}</TextField.Caption>
<Input.Caption>{WRONG_AUTH_CODE_MESSAGE}</Input.Caption>
) : (
isSMSSent && <TextField.Caption>{timeCaption}</TextField.Caption>
isSMSSent && <Input.Caption>{timeCaption}</Input.Caption>
)
}
/>
Expand Down
10 changes: 0 additions & 10 deletions apps/bottle/src/app/profile/create/CreateProfileProvider.tsx

This file was deleted.

13 changes: 0 additions & 13 deletions apps/bottle/src/app/profile/create/SignupProvider.tsx

This file was deleted.

13 changes: 2 additions & 11 deletions apps/bottle/src/app/profile/create/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,13 @@
import { getServerSideTokens } from '@/features/server/serverSideTokens';
import { StepProvider } from '@/features/steps/StepProvider';
import { ServerFetchBoundary } from '@/store/query/ServerFetchBoundary';
import { regionsQueryOptions } from '@/store/query/useRegionsQuery';
import { userInfoQueryOptions } from '@/store/query/useUserInfoQuery';
import { ReactNode, Suspense } from 'react';
import type { ReactNode } from 'react';

export default async function CreateProfileLayout({ children }: { children: ReactNode }) {
const tokens = getServerSideTokens();

const serverFetchOptions = [regionsQueryOptions(tokens), userInfoQueryOptions(tokens)];

return (
<Suspense>
<ServerFetchBoundary fetchOptions={serverFetchOptions}>
<StepProvider maxStep={10} uri="/profile/create">
{children}
</StepProvider>
</ServerFetchBoundary>
</Suspense>
);
return <ServerFetchBoundary fetchOptions={serverFetchOptions}>{children}</ServerFetchBoundary>;
}
3 changes: 1 addition & 2 deletions apps/bottle/src/app/profile/create/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import { Profile } from '@/models/profile';
import { User } from '@/models/user';
import { useProfileMutation } from '@/store/mutation/useProfileMuatation';
import { useRouter } from 'next/navigation';
import { CreateProfileProvider } from './CreateProfileProvider';

const MAX_STEPS = 10;

Expand Down Expand Up @@ -142,5 +141,5 @@ export default function CreateProfilePage() {
</ProfileLayout>,
];

return <CreateProfileProvider>{steps[currentStep - 1]}</CreateProfileProvider>;
return <>{steps[currentStep - 1]}</>;
}
31 changes: 31 additions & 0 deletions apps/bottle/src/app/profile/edit/(items)/introduction/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
'use client';

import { Introduction } from '@/components/intro/introduction';
import { useIntroductionMutation } from '@/store/mutation/useIntroductionMutation';
import { useCurrentUserProfileQuery } from '@/store/query/useCurrentUserProfileQuery';
import { useRouter } from 'next/navigation';

export default function IntroductionEditPage() {
const {
data: { introduction },
} = useCurrentUserProfileQuery();
const router = useRouter();

const { mutate } = useIntroductionMutation({ type: 'edit' });

const initialAnswer = introduction[0]?.answer ?? '';

return (
<Introduction
initialValue={introduction}
onNext={introduction => {
if (introduction[0]?.answer === initialAnswer) {
router.back();
return;
}
mutate(introduction);
}}
ctaButtonText="완료"
/>
);
}
26 changes: 20 additions & 6 deletions apps/bottle/src/app/profile/edit/IntroductionArea.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@

import { Card } from '@/components/common/card';
import { useCurrentUserProfileQuery } from '@/store/query/useCurrentUserProfileQuery';
import { Paragraph, spacings } from '@bottlesteam/ui';
import { introductionBoxStyle } from './profileEditStyle.css';
import { Asset, Paragraph, spacings } from '@bottlesteam/ui';
import Link from 'next/link';
import { introductionBoxStyle, introductionTextBoxStyle } from './profileEditStyle.css';

const NO_INTRODUCTION_FALLBACK_TEXT = '아직 자기소개를 작성하지 않았어요';

export function IntroductionArea() {
const {
Expand All @@ -12,10 +15,21 @@ export function IntroductionArea() {

return (
<Card style={{ marginTop: spacings.xl }}>
<Paragraph color="black100" typography="st1">
내가 쓴 편지
</Paragraph>
<div className={introductionBoxStyle}>{introduction[0]?.answer}</div>
<Link href="/profile/edit/introduction">
<div className={introductionTextBoxStyle}>
<Paragraph color="black100" typography="st1">
내가 쓴 편지
</Paragraph>
{introduction != null && (
<button style={{ background: 'none', border: 'none' }}>
<Asset type="icon-right" />
</button>
)}
</div>
</Link>
<div className={introductionBoxStyle}>
{introduction != null ? introduction[0]?.answer : NO_INTRODUCTION_FALLBACK_TEXT}
</div>
</Card>
);
}
8 changes: 8 additions & 0 deletions apps/bottle/src/app/profile/edit/profileEditStyle.css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@ export const contentsContainerStyle = style({
},
});

export const introductionTextBoxStyle = style({
width: '100%',
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
});

export const introductionBoxStyle = style({
width: '100%',
height: 'auto',
Expand All @@ -34,6 +41,7 @@ export const profileItemStyle = style({
alignItems: 'center',
gap: spacings.xs,
});

export const profileItemLeftStyle = style({
display: 'flex',
flexDirection: 'column',
Expand Down
Loading
Loading