Skip to content

Commit

Permalink
feat(bottle, ui): User image and introduction create, edit (#75)
Browse files Browse the repository at this point in the history
* wip

* feat(bottle): question card

* feat(ui): set bottom sheet overlay, body wrapper zIndex

* fix(bottle): page layout padding

* fix(bottle): import order lint

* chore(e2e): update playwright version

* chore: update lockfile

* feat(bottle): IntroductionV2

* feat(bottle): auto create intro

* fix(eslint-config): disable no-redeclare rule

* fix(ui): value prop missing bug

* fix(bottle): storage integration bug

* feat(ui): ImageInputs component

* feat(ui): add purple600 color

* feat(ui): add icon-close, icon-check white version

* feat(bottle): image upload ui and guide carousel

* feat(bottle): upload image using presigned url

* feat(ui): add maxLength prop to Textarea component

* fix(ui): use Blob over base64

* feat(bottle): profile images edit

* fix(bottle): change max images to 1
  • Loading branch information
stakbucks authored Oct 29, 2024
1 parent 2b1bf11 commit 48f31de
Show file tree
Hide file tree
Showing 71 changed files with 4,094 additions and 1,861 deletions.
3 changes: 3 additions & 0 deletions apps/bottle/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
"@radix-ui/react-slot": "^1.1.0",
"@tanstack/react-query": "^5.51.21",
"cookies-next": "^4.2.1",
"embla-carousel-autoplay": "^8.3.0",
"embla-carousel-react": "^8.3.0",
"es-hangul": "^2.1.0",
"es-toolkit": "^1.13.1",
"next": "14.2.4",
"overlay-kit": "^1.3.0",
Expand Down
5 changes: 3 additions & 2 deletions apps/bottle/src/app/admin/login/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use client';

import { Header } from '@/components/common/header';
import { ProfileLayout } from '@/components/profile/layout';
import { POST } from '@/features/server';
import { Step } from '@/features/steps/StepContainer';
import { spacings, Input } from '@bottlesteam/ui';
Expand Down Expand Up @@ -50,7 +51,7 @@ export default function LoginPage() {
};

return (
<>
<ProfileLayout.Contents>
<Header />
<Step>
<Step.Title style={{ marginTop: spacings.xl }}>{'인증을 진행할게요'}</Step.Title>
Expand Down Expand Up @@ -82,6 +83,6 @@ export default function LoginPage() {
로그인
</Step.FixedButton>
</Step>
</>
</ProfileLayout.Contents>
);
}
5 changes: 3 additions & 2 deletions apps/bottle/src/app/admin/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use client';

import { Header } from '@/components/common/header';
import { ProfileLayout } from '@/components/profile/layout';
import { POST } from '@/features/server';
import { getClientSideTokens } from '@/features/server/clientSideTokens';
import { Step } from '@/features/steps/StepContainer';
Expand All @@ -9,7 +10,7 @@ import Link from 'next/link';

export default function AdminPage() {
return (
<>
<ProfileLayout.Contents>
<Header />
<Step>
<Step.Title style={{ margin: `${spacings.xl} 0` }}>{'뭐할래?'}</Step.Title>
Expand Down Expand Up @@ -47,6 +48,6 @@ export default function AdminPage() {
</Link>
</div>
</Step>
</>
</ProfileLayout.Contents>
);
}
3 changes: 3 additions & 0 deletions apps/bottle/src/app/bottle/[...slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ interface Props {
params: { slug: [BottleType, number] };
}

/**
* @deprecated use '/bottles/[type]/[id]' instead
*/
export default function BottleItemPage({
params: {
slug: [type, id],
Expand Down
121 changes: 64 additions & 57 deletions apps/bottle/src/app/bottles/Bottles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import NO_BOTTLE_IMAGE from '@/assets/images/no-bottle.webp';
import { Control } from '@/components/common/control';
import { Header } from '@/components/common/header';
import { ProfileLayout } from '@/components/profile/layout';
import { AppBridgeMessageType, useAppBridge } from '@/features/app-bridge';
import { Asset, Button, Paragraph } from '@bottlesteam/ui';
import Image from 'next/image';
Expand All @@ -12,6 +13,10 @@ import { BottlesList } from './_components/BottlesList';
import { contentsContainer, controlStyle } from './pageStyle.css';

// NOTE: 'random' and 'recommendation' are the same. 'random' will be deprecated soon.
/**
* @deprecated use '/bottles/[type]' instead
* support iOS v1.0.9, android v1.0.2
*/
export type BottleType = 'random' | 'sent' | 'recommendation';

export function Bottles() {
Expand All @@ -28,64 +33,66 @@ export function Bottles() {
<Asset type="icon-arrow-left" />
</button>
</Header>
<div className={contentsContainer}>
<Control value={type}>
<div className={controlStyle}>
<Control.Item onClick={() => setType('random')} value={'random'}>
<Button variant="outlined" size="sm">
떠다니는 보틀
</Button>
</Control.Item>
<Control.Item onClick={() => setType('sent')} value={'sent'}>
<Button variant="outlined" size="sm">
마음이 담긴 보틀
</Button>
</Control.Item>
</div>
</Control>
<BottlesList
top={data => (
<BottlesList.Top>
{name => (
<Paragraph typography="t1" color="black100">
{type === 'random'
? data.randomBottles?.length > 0
? `${name}님에게\n추천하는 분들이에요!`
: '아직 주변에 새로운\n보틀이 없어요'
: data.sentBottles?.length > 0
? `${name}님을 마음에\n들어한 분들이에요`
: '아직 받은 보틀이 없어요'}
</Paragraph>
)}
</BottlesList.Top>
)}
>
{data => {
const bottles = type === 'random' ? data.randomBottles : data.sentBottles;
return bottles.length === 0 ? (
<div
style={{
display: 'flex',
justifyContent: 'center',
width: '100%',
aspectRatio: '1 / 1',
padding: '60px',
}}
>
<div style={{ width: '100%', height: '100%', position: 'relative' }}>
<Image src={NO_BOTTLE_IMAGE} alt="no bottle" fill objectFit="contain" />
<ProfileLayout.Contents>
<div className={contentsContainer}>
<Control value={type}>
<div className={controlStyle}>
<Control.Item onClick={() => setType('random')} value={'random'}>
<Button variant="outlined" size="sm">
떠다니는 보틀
</Button>
</Control.Item>
<Control.Item onClick={() => setType('sent')} value={'sent'}>
<Button variant="outlined" size="sm">
마음이 담긴 보틀
</Button>
</Control.Item>
</div>
</Control>
<BottlesList
top={data => (
<BottlesList.Top>
{name => (
<Paragraph typography="t1" color="black100">
{type === 'random'
? data.randomBottles?.length > 0
? `${name}님에게\n추천하는 분들이에요!`
: '아직 주변에 새로운\n보틀이 없어요'
: data.sentBottles?.length > 0
? `${name}님을 마음에\n들어한 분들이에요`
: '아직 받은 보틀이 없어요'}
</Paragraph>
)}
</BottlesList.Top>
)}
>
{data => {
const bottles = type === 'random' ? data.randomBottles : data.sentBottles;
return bottles.length === 0 ? (
<div
style={{
display: 'flex',
justifyContent: 'center',
width: '100%',
aspectRatio: '1 / 1',
padding: '60px',
}}
>
<div style={{ width: '100%', height: '100%', position: 'relative' }}>
<Image src={NO_BOTTLE_IMAGE} alt="no bottle" fill objectFit="contain" />
</div>
</div>
</div>
) : (
bottles?.map(bottle => (
<Link key={bottle.id} href={`/bottles/${type}/${bottle.id}`}>
<BottlesList.Item bottle={bottle} />
</Link>
))
);
}}
</BottlesList>
</div>
) : (
bottles?.map(bottle => (
<Link key={bottle.id} href={`/bottles/${type}/${bottle.id}`}>
<BottlesList.Item bottle={bottle} />
</Link>
))
);
}}
</BottlesList>
</div>
</ProfileLayout.Contents>
</>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export function Recommendations() {
} = useRecommendationBottlesQuery();

return (
<>
<ProfileLayout.Contents>
{randomBottles.length > 0 ? (
<>
<ProfileLayout.Title>{`${currentUser.name}님에게\n추천하는 분들이에요!`}</ProfileLayout.Title>
Expand Down Expand Up @@ -55,6 +55,6 @@ export function Recommendations() {
<Fallback.Subtitle>{`보틀은 ${currentUser.name}님과 케미가 통하는\n상대를 엄선해 추천드리고 있어요`}</Fallback.Subtitle>
</Fallback>
)}
</>
</ProfileLayout.Contents>
);
}
4 changes: 2 additions & 2 deletions apps/bottle/src/app/bottles/sents/Sents.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export function Sents() {
} = useSentBottlesQuery();

return (
<>
<ProfileLayout.Contents>
{sentBottles.length > 0 ? (
<>
<ProfileLayout.Title
Expand Down Expand Up @@ -57,6 +57,6 @@ export function Sents() {
<Fallback.Subtitle>나를 마음에 들어할 상대는 누굴까요 👀</Fallback.Subtitle>
</Fallback>
)}
</>
</ProfileLayout.Contents>
);
}
5 changes: 4 additions & 1 deletion apps/bottle/src/app/create-profile/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,11 @@ const steps = [
<KaKaoId />
</Step>,
] as const;

/**
* @deprecated
* @deprecated use 'profile/create' instead
* support iOS v1.0.8
* support android v1.0.1
*/
export default function CreateProfilePage() {
const router = useRouter();
Expand Down
21 changes: 12 additions & 9 deletions apps/bottle/src/app/error.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import BasketImage from '@/assets/images/basket.webp';
import { Header } from '@/components/common/header';
import { ProfileLayout } from '@/components/profile/layout';
import { AppBridgeMessageType, useAppBridge } from '@/features/app-bridge';
import { Asset, Button, Paragraph, spacings } from '@bottlesteam/ui';
import Image from 'next/image';
Expand Down Expand Up @@ -31,15 +32,17 @@ export default function DefaultErrorPage({ error, reset }: ErrorPageProps) {
<Asset type="icon-arrow-left" />
</button>
</Header>
<Paragraph typography="t2" color="black100" style={{ marginTop: spacings.xl, marginBottom: spacings.xxl }}>
{'앗, 오류가 발생했어요!\n보틀을 다시 실행해 주세요'}
</Paragraph>
<div className={errorImageContainer}>
<Image alt="basket" src={BasketImage} width={250} height={250} />
<Button variant="solid" size="sm" onClick={reset}>
다시 시도하기
</Button>
</div>
<ProfileLayout.Contents>
<Paragraph typography="t2" color="black100" style={{ marginTop: spacings.xl, marginBottom: spacings.xxl }}>
{'앗, 오류가 발생했어요!\n보틀을 다시 실행해 주세요'}
</Paragraph>
<div className={errorImageContainer}>
<Image alt="basket" src={BasketImage} width={250} height={250} />
<Button variant="solid" size="sm" onClick={reset}>
다시 시도하기
</Button>
</div>
</ProfileLayout.Contents>
</>
);
}
21 changes: 21 additions & 0 deletions apps/bottle/src/app/intro/create/GradientBackground.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import Image from 'next/image';
import Gradient from './gradient.png';

export function GradientBackground() {
return (
<div
style={{
width: 776,
height: 613,
userSelect: 'none',
position: 'absolute',
top: 48,
zIndex: 0,
left: '50%',
transform: 'translateX(-50%)',
}}
>
<Image src={Gradient} alt="gradient" priority fill aria-hidden />
</div>
);
}
Binary file added apps/bottle/src/app/intro/create/gradient.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 48f31de

Please sign in to comment.