Skip to content

Commit

Permalink
feat(bottle, ui): user self introduction (#63)
Browse files Browse the repository at this point in the history
* fix(bottle): removed deprecated code

* fix(bottle): removed deprecated code

* feat(bottle): funnel setup

* refactor(bottle, ui): change texfield component name to input

* feat(ui): textarea 컴포넌트 구현

* feat(ui): add maxLength prop for textarea

* refactor(bottle): make SelectedProfile component customizable

* feat(bottle): create introduction

* feat(bottle): introduction create mutation

* feat(ui): plus icon asset

* feat(bottle): edit introduction
  • Loading branch information
stakbucks authored Sep 28, 2024
1 parent e904b92 commit 21b4c4a
Show file tree
Hide file tree
Showing 41 changed files with 570 additions and 140 deletions.
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

0 comments on commit 21b4c4a

Please sign in to comment.