Skip to content

Commit

Permalink
feat(bottle): fallback ui when there is no bottle
Browse files Browse the repository at this point in the history
  • Loading branch information
stakbucks committed Oct 3, 2024
1 parent c962224 commit 758ce08
Show file tree
Hide file tree
Showing 18 changed files with 125 additions and 58 deletions.
2 changes: 1 addition & 1 deletion apps/bottle/src/app/bottles/Bottles.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use client';

import NO_BOTTLE_IMAGE from '@/assets/no-bottle.webp';
import NO_BOTTLE_IMAGE from '@/assets/images/no-bottle.webp';
import { Control } from '@/components/common/control';
import { Header } from '@/components/common/header';
import { AppBridgeMessageType, useAppBridge } from '@/features/app-bridge';
Expand Down
46 changes: 30 additions & 16 deletions apps/bottle/src/app/bottles/recommendations/Recommendations.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
'use client';

import TelescopeImage from '@/assets/images/telescope.webp';
import { BottleCard } from '@/components/common/bottle-card';
import { Fallback } from '@/components/common/fallback';
import { ProfileLayout } from '@/components/profile/layout';
import { useRecommendationBottlesQuery } from '@/store/query/useRecommendationBottlesQuery';
import { useUserInfoQuery } from '@/store/query/useUserInfoQuery';
Expand All @@ -9,25 +11,37 @@ import { pick } from 'es-toolkit';

export function Recommendations() {
const { data: currentUser } = useUserInfoQuery();
const { data: recommendationBottles } = useRecommendationBottlesQuery();
const {
data: { randomBottles },
} = useRecommendationBottlesQuery();

return (
<>
<ProfileLayout.Title>{`${currentUser.name}님에게\n추천하는 분들이에요!`}</ProfileLayout.Title>
<ProfileLayout.Subtitle style={{ marginTop: spacings.sm }}>
시간이 지나면 새로운 분들을 추천해 드려요
</ProfileLayout.Subtitle>
<section style={{ marginTop: spacings.xxl, display: 'flex', flexDirection: 'column', gap: spacings.md }}>
{recommendationBottles.randomBottles.map(bottle => (
<BottleCard key={bottle.id}>
<BottleCard.TimeTag>{bottle.expiredAt}</BottleCard.TimeTag>
<BottleCard.Introduction>{bottle.introduction[0]?.answer}</BottleCard.Introduction>
<BottleCard.UserInformation
{...pick(bottle, ['userName', 'age', 'mbti', 'userImageUrl', 'lastActivatedAt'])}
/>
</BottleCard>
))}
</section>
{randomBottles.length > 0 ? (
<>
<ProfileLayout.Title>{`${currentUser.name}님에게\n추천하는 분들이에요!`}</ProfileLayout.Title>
<ProfileLayout.Subtitle style={{ marginTop: spacings.sm }}>
시간이 지나면 새로운 분들을 추천해 드려요
</ProfileLayout.Subtitle>
<section style={{ marginTop: spacings.xxl, display: 'flex', flexDirection: 'column', gap: spacings.md }}>
{randomBottles.map(bottle => (
<BottleCard key={bottle.id}>
<BottleCard.TimeTag>{bottle.expiredAt}</BottleCard.TimeTag>
<BottleCard.Introduction>{bottle.introduction[0]?.answer}</BottleCard.Introduction>
<BottleCard.UserInformation
{...pick(bottle, ['userName', 'age', 'mbti', 'userImageUrl', 'lastActivatedAt'])}
/>
</BottleCard>
))}
</section>
</>
) : (
<Fallback marginTop={94}>
<Fallback.Image src={TelescopeImage} alt="fallback image" />
<Fallback.Title>꼭 맞는 상대를 찾는 중이에요</Fallback.Title>
<Fallback.Subtitle>{`보틀은 ${currentUser.name}님과 케미가 통하는\n상대를 엄선해 추천드리고 있어요`}</Fallback.Subtitle>
</Fallback>
)}
</>
);
}
16 changes: 0 additions & 16 deletions apps/bottle/src/app/bottles/sents/HeaderArea.tsx

This file was deleted.

48 changes: 30 additions & 18 deletions apps/bottle/src/app/bottles/sents/Sents.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
'use client';

import CoconutImage from '@/assets/images/coconut.webp';
import { BottleCard } from '@/components/common/bottle-card';
import { Fallback } from '@/components/common/fallback';
import { ProfileLayout } from '@/components/profile/layout';
import { useSentBottlesQuery } from '@/store/query/useSentBottlesQuery';
import { useUserInfoQuery } from '@/store/query/useUserInfoQuery';
Expand All @@ -9,27 +11,37 @@ import { pick } from 'es-toolkit';

export function Sents() {
const { data: currentUser } = useUserInfoQuery();
const { data: sentBottlesData } = useSentBottlesQuery();

console.log('DATA', sentBottlesData.sentBottles);
const {
data: { sentBottles },
} = useSentBottlesQuery();

return (
<>
<ProfileLayout.Title>{`${currentUser.name}님을 마음에\n들어한 분들이에요`}</ProfileLayout.Title>
<ProfileLayout.Subtitle style={{ marginTop: spacings.sm }}>
시간 내에 보틀을 열지 않으면 사라져요
</ProfileLayout.Subtitle>
<section style={{ marginTop: spacings.xxl, display: 'flex', flexDirection: 'column', gap: spacings.md }}>
{sentBottlesData.sentBottles.map(bottle => (
<BottleCard key={bottle.id}>
<BottleCard.TimeTag>{bottle.expiredAt}</BottleCard.TimeTag>
<BottleCard.Introduction>{bottle.introduction[0]?.answer}</BottleCard.Introduction>
<BottleCard.UserInformation
{...pick(bottle, ['userName', 'age', 'mbti', 'userImageUrl', 'likeEmoji', 'lastActivatedAt'])}
/>
</BottleCard>
))}
</section>
{sentBottles.length > 0 ? (
<>
<ProfileLayout.Title>{`${currentUser.name}님을 마음에\n들어한 분들이에요`}</ProfileLayout.Title>
<ProfileLayout.Subtitle style={{ marginTop: spacings.sm }}>
시간 내에 보틀을 열지 않으면 사라져요
</ProfileLayout.Subtitle>
<section style={{ marginTop: spacings.xxl, display: 'flex', flexDirection: 'column', gap: spacings.md }}>
{sentBottles.map(bottle => (
<BottleCard key={bottle.id}>
<BottleCard.TimeTag>{bottle.expiredAt}</BottleCard.TimeTag>
<BottleCard.Introduction>{bottle.introduction[0]?.answer}</BottleCard.Introduction>
<BottleCard.UserInformation
{...pick(bottle, ['userName', 'age', 'mbti', 'userImageUrl', 'likeEmoji', 'lastActivatedAt'])}
/>
</BottleCard>
))}
</section>
</>
) : (
<Fallback marginTop={94}>
<Fallback.Image src={CoconutImage} alt="fallback image" />
<Fallback.Title>조금만 기다려 볼까요?</Fallback.Title>
<Fallback.Subtitle>나를 마음에 들어할 상대는 누굴까요 👀</Fallback.Subtitle>
</Fallback>
)}
</>
);
}
4 changes: 2 additions & 2 deletions apps/bottle/src/app/bottles/sents/page.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { Header } from '@/components/common/header';
import { ProfileLayout } from '@/components/profile/layout';
import { getServerSideTokens } from '@/features/server/serverSideTokens';
import { ServerFetchBoundary } from '@/store/query/ServerFetchBoundary';
import { sentBottlesQueryOptions } from '@/store/query/useSentBottlesQuery';
import { userInfoQueryOptions } from '@/store/query/useUserInfoQuery';
import { Suspense } from 'react';
import { HeaderArea } from './HeaderArea';
import { Sents } from './Sents';

export default function SentBottlesPage() {
Expand All @@ -13,7 +13,7 @@ export default function SentBottlesPage() {

return (
<ProfileLayout hasCTAButton={false}>
<HeaderArea />
<Header />
<Suspense>
<ServerFetchBoundary fetchOptions={serverFetchOptions}>
<Sents />
Expand Down
2 changes: 1 addition & 1 deletion apps/bottle/src/app/error.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use client';

import BasketImage from '@/assets/basket.webp';
import BasketImage from '@/assets/images/basket.webp';
import { Header } from '@/components/common/header';
import { AppBridgeMessageType, useAppBridge } from '@/features/app-bridge';
import { Asset, Button, Paragraph, spacings } from '@bottlesteam/ui';
Expand Down
2 changes: 1 addition & 1 deletion apps/bottle/src/app/not-found.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use client';

import BasketImage from '@/assets/basket.webp';
import BasketImage from '@/assets/images/basket.webp';
import { Header } from '@/components/common/header';
import { AppBridgeMessageType, useAppBridge } from '@/features/app-bridge';
import { Asset, Button, Paragraph, spacings } from '@bottlesteam/ui';
Expand Down
File renamed without changes.
Binary file added apps/bottle/src/assets/images/coconut.webp
Binary file not shown.
File renamed without changes.
Binary file added apps/bottle/src/assets/images/telescope.webp
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ type Props =
| Pick<SentBottlePreview, 'userName' | 'age' | 'mbti' | 'userImageUrl' | 'lastActivatedAt' | 'likeEmoji'>;

export function UserInformationArea({ userName, userImageUrl, age, mbti, lastActivatedAt, ...rest }: Props) {
console.log('????', rest.likeEmoji, rest);
return (
<div className={userInformationAreaStyle}>
<div className={userPreviewStyle}>
Expand All @@ -36,7 +35,7 @@ export function UserInformationArea({ userName, userImageUrl, age, mbti, lastAct
<div style={{ display: 'flex', alignItems: 'center', gap: spacings.xxs }}>
<Asset type="icon-clock" />
<Paragraph typography="ca" color="neutral900">
{lastActivatedAt}
{lastActivatedAt} 접속
</Paragraph>
</div>
</div>
Expand All @@ -46,7 +45,6 @@ export function UserInformationArea({ userName, userImageUrl, age, mbti, lastAct
{Object.hasOwn(rest, 'likeEmoji') && (
<Paragraph typography="t2" style={{ position: 'absolute', bottom: -2, left: -8 }}>
{(rest as any).likeEmoji as string}
{/* {'😘'} */}
</Paragraph>
)}
</div>
Expand Down
5 changes: 5 additions & 0 deletions apps/bottle/src/components/common/fallback/Image.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import NextImage, { ImageProps as NextImageProps } from 'next/image';

export function Image(props: Omit<NextImageProps, 'width' | 'height' | 'className'>) {
return <NextImage {...props} width={180} height={180} />;
}
10 changes: 10 additions & 0 deletions apps/bottle/src/components/common/fallback/Subtitle.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Paragraph, spacings } from '@bottlesteam/ui';
import type { ReactNode } from 'react';

export function Subtitle({ children }: { children: ReactNode }) {
return (
<Paragraph style={{ marginTop: spacings.xs }} color="neutral600" typography="bo">
{children}
</Paragraph>
);
}
10 changes: 10 additions & 0 deletions apps/bottle/src/components/common/fallback/Title.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Paragraph, spacings } from '@bottlesteam/ui';
import type { ReactNode } from 'react';

export function Title({ children }: { children: ReactNode }) {
return (
<Paragraph typography="st1" style={{ marginTop: spacings.xl }}>
{children}
</Paragraph>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { style } from '@vanilla-extract/css';

export const fallbackContainerStyle = style({
width: '100%',
height: 'auto',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
});
24 changes: 24 additions & 0 deletions apps/bottle/src/components/common/fallback/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import type { ReactNode } from 'react';
import { Image } from './Image';
import { Subtitle } from './Subtitle';
import { Title } from './Title';
import { fallbackContainerStyle } from './fallbackStyle.css';

interface FallbackProps {
marginTop?: number;
children: ReactNode;
}

function FallbackContainer({ children, marginTop = 0 }: FallbackProps) {
return (
<section style={{ marginTop }} className={fallbackContainerStyle}>
{children}
</section>
);
}

export const Fallback = Object.assign(FallbackContainer, {
Image,
Title,
Subtitle,
});
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export const recommendationBottlesQueryOptions = (tokens: Tokens): UseSuspenseQu
queryKey: ['bottles', 'recommendation'],
// NOTE: should ALWAYS be stale
queryFn: () => GET<RandomBottlesQuery>(`/api/v2/bottles/random`, tokens, createInit(tokens.accessToken)),
staleTime: 0,
});

export function useRecommendationBottlesQuery() {
Expand Down

0 comments on commit 758ce08

Please sign in to comment.