From c9622244413141468ab5167e481a01141c8317b6 Mon Sep 17 00:00:00 2001 From: stakbucks Date: Thu, 3 Oct 2024 15:00:22 +0900 Subject: [PATCH] feat(bottle): sent bottles page --- .../recommendations/Recommendations.tsx | 13 +++---- .../src/app/bottles/recommendations/page.tsx | 15 ++++---- .../src/app/bottles/sents/HeaderArea.tsx | 16 +++++++++ apps/bottle/src/app/bottles/sents/Sents.tsx | 35 +++++++++++++++++++ apps/bottle/src/app/bottles/sents/page.tsx | 24 +++++++++++++ .../common/bottle-card/IntroductionBox.tsx | 11 +++++- .../bottle-card/UserInformationArea.tsx | 12 ++++--- .../common/bottle-card/bottleCardstyle.css.ts | 3 +- .../src/components/profile/layout/index.tsx | 5 +-- .../profile/layout/profileLayoutStyle.css.ts | 27 ++++++++++---- apps/bottle/src/models/bottle.ts | 6 ++-- .../query/useRecommendationBottlesQuery.ts | 15 ++------ .../src/store/query/useSentBottlesQuery.ts | 20 +++++++++++ 13 files changed, 157 insertions(+), 45 deletions(-) create mode 100644 apps/bottle/src/app/bottles/sents/HeaderArea.tsx create mode 100644 apps/bottle/src/app/bottles/sents/Sents.tsx create mode 100644 apps/bottle/src/app/bottles/sents/page.tsx create mode 100644 apps/bottle/src/store/query/useSentBottlesQuery.ts diff --git a/apps/bottle/src/app/bottles/recommendations/Recommendations.tsx b/apps/bottle/src/app/bottles/recommendations/Recommendations.tsx index 8e55582..a26f377 100644 --- a/apps/bottle/src/app/bottles/recommendations/Recommendations.tsx +++ b/apps/bottle/src/app/bottles/recommendations/Recommendations.tsx @@ -14,19 +14,16 @@ export function Recommendations() { return ( <> {`${currentUser.name}님에게\n추천하는 분들이에요!`} - 시간이 지나면 새로운 분들을 추천해 드려요 + + 시간이 지나면 새로운 분들을 추천해 드려요 +
{recommendationBottles.randomBottles.map(bottle => ( {bottle.expiredAt} - - { - // FIXME - '어떤 날은 아침에 눈이 번쩍 떠지는 게 힘이 펄펄 나는 것 같은가 하면 또 어떤 날은 몸이 진흙으로 만들어진 것 같은 때가 있습니다...' - } - + {bottle.introduction[0]?.answer} ))} diff --git a/apps/bottle/src/app/bottles/recommendations/page.tsx b/apps/bottle/src/app/bottles/recommendations/page.tsx index 23579ae..2213a96 100644 --- a/apps/bottle/src/app/bottles/recommendations/page.tsx +++ b/apps/bottle/src/app/bottles/recommendations/page.tsx @@ -1,21 +1,24 @@ import { ProfileLayout } from '@/components/profile/layout'; import { getServerSideTokens } from '@/features/server/serverSideTokens'; import { ServerFetchBoundary } from '@/store/query/ServerFetchBoundary'; -import { bottlesQueryOptions } from '@/store/query/useBottlesQuery'; +import { recommendationBottlesQueryOptions } from '@/store/query/useRecommendationBottlesQuery'; import { userInfoQueryOptions } from '@/store/query/useUserInfoQuery'; +import { Suspense } from 'react'; import { HeaderArea } from './HeaderArea'; import { Recommendations } from './Recommendations'; export default function RecommendationsPage() { const tokens = getServerSideTokens(); - const serverFetchOptions = [userInfoQueryOptions(tokens), bottlesQueryOptions(tokens)]; + const serverFetchOptions = [userInfoQueryOptions(tokens), recommendationBottlesQueryOptions(tokens)]; return ( - + - - - + + + + + ); } diff --git a/apps/bottle/src/app/bottles/sents/HeaderArea.tsx b/apps/bottle/src/app/bottles/sents/HeaderArea.tsx new file mode 100644 index 0000000..eec5e62 --- /dev/null +++ b/apps/bottle/src/app/bottles/sents/HeaderArea.tsx @@ -0,0 +1,16 @@ +'use client'; + +import { Header } from '@/components/common/header'; +import { AppBridgeMessageType, useAppBridge } from '@/features/app-bridge'; + +export function HeaderArea() { + const { send } = useAppBridge(); + + return ( +
{ + send({ type: AppBridgeMessageType.WEB_VIEW_CLOSE }); + }} + /> + ); +} diff --git a/apps/bottle/src/app/bottles/sents/Sents.tsx b/apps/bottle/src/app/bottles/sents/Sents.tsx new file mode 100644 index 0000000..04e7d43 --- /dev/null +++ b/apps/bottle/src/app/bottles/sents/Sents.tsx @@ -0,0 +1,35 @@ +'use client'; + +import { BottleCard } from '@/components/common/bottle-card'; +import { ProfileLayout } from '@/components/profile/layout'; +import { useSentBottlesQuery } from '@/store/query/useSentBottlesQuery'; +import { useUserInfoQuery } from '@/store/query/useUserInfoQuery'; +import { spacings } from '@bottlesteam/ui'; +import { pick } from 'es-toolkit'; + +export function Sents() { + const { data: currentUser } = useUserInfoQuery(); + const { data: sentBottlesData } = useSentBottlesQuery(); + + console.log('DATA', sentBottlesData.sentBottles); + + return ( + <> + {`${currentUser.name}님을 마음에\n들어한 분들이에요`} + + 시간 내에 보틀을 열지 않으면 사라져요 + +
+ {sentBottlesData.sentBottles.map(bottle => ( + + {bottle.expiredAt} + {bottle.introduction[0]?.answer} + + + ))} +
+ + ); +} diff --git a/apps/bottle/src/app/bottles/sents/page.tsx b/apps/bottle/src/app/bottles/sents/page.tsx new file mode 100644 index 0000000..7241abb --- /dev/null +++ b/apps/bottle/src/app/bottles/sents/page.tsx @@ -0,0 +1,24 @@ +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() { + const tokens = getServerSideTokens(); + const serverFetchOptions = [userInfoQueryOptions(tokens), sentBottlesQueryOptions(tokens)]; + + return ( + + + + + + + + + ); +} diff --git a/apps/bottle/src/components/common/bottle-card/IntroductionBox.tsx b/apps/bottle/src/components/common/bottle-card/IntroductionBox.tsx index f3c2715..81a92f3 100644 --- a/apps/bottle/src/components/common/bottle-card/IntroductionBox.tsx +++ b/apps/bottle/src/components/common/bottle-card/IntroductionBox.tsx @@ -5,7 +5,16 @@ import { introductionBoxStyle } from './bottleCardstyle.css'; export function IntroductionBox({ children }: { children: ReactNode }) { return (
- + {children}
diff --git a/apps/bottle/src/components/common/bottle-card/UserInformationArea.tsx b/apps/bottle/src/components/common/bottle-card/UserInformationArea.tsx index ea2b922..0a5b09f 100644 --- a/apps/bottle/src/components/common/bottle-card/UserInformationArea.tsx +++ b/apps/bottle/src/components/common/bottle-card/UserInformationArea.tsx @@ -9,10 +9,11 @@ import { } from './bottleCardstyle.css'; type Props = - | Pick - | Pick; + | Pick + | Pick; export function UserInformationArea({ userName, userImageUrl, age, mbti, lastActivatedAt, ...rest }: Props) { + console.log('????', rest.likeEmoji, rest); return (
@@ -42,8 +43,11 @@ export function UserInformationArea({ userName, userImageUrl, age, mbti, lastAct
- {'likeEmjoi' in rest && ( - {rest.likeEmjoi as string} + {Object.hasOwn(rest, 'likeEmoji') && ( + + {(rest as any).likeEmoji as string} + {/* {'😘'} */} + )}
diff --git a/apps/bottle/src/components/common/bottle-card/bottleCardstyle.css.ts b/apps/bottle/src/components/common/bottle-card/bottleCardstyle.css.ts index ec20ad8..b7ec6be 100644 --- a/apps/bottle/src/components/common/bottle-card/bottleCardstyle.css.ts +++ b/apps/bottle/src/components/common/bottle-card/bottleCardstyle.css.ts @@ -20,11 +20,10 @@ export const timeTagStyle = style({ export const introductionBoxStyle = style({ width: '100%', - height: 'auto', + height: '95px', backgroundColor: colors.neutral100, padding: spacings.md, borderRadius: radius.md, - maxLines: 3, }); export const userInformationAreaStyle = style({ diff --git a/apps/bottle/src/components/profile/layout/index.tsx b/apps/bottle/src/components/profile/layout/index.tsx index 546619e..10d8553 100644 --- a/apps/bottle/src/components/profile/layout/index.tsx +++ b/apps/bottle/src/components/profile/layout/index.tsx @@ -4,10 +4,11 @@ import { containerStyle } from './profileLayoutStyle.css'; interface Props { children: ReactNode; + hasCTAButton?: boolean; } -function ProfileContainer({ children }: Props) { - return
{children}
; +function ProfileContainer({ children, hasCTAButton = true }: Props) { + return
{children}
; } function Title({ children, ...rest }: Omit) { diff --git a/apps/bottle/src/components/profile/layout/profileLayoutStyle.css.ts b/apps/bottle/src/components/profile/layout/profileLayoutStyle.css.ts index ae5b51d..8c6b79a 100644 --- a/apps/bottle/src/components/profile/layout/profileLayoutStyle.css.ts +++ b/apps/bottle/src/components/profile/layout/profileLayoutStyle.css.ts @@ -1,5 +1,6 @@ import { CTA_HEIGHT, spacings } from '@bottlesteam/ui'; import { style } from '@vanilla-extract/css'; +import { recipe } from '@vanilla-extract/recipes'; /** * NOTE: This is a trick to make sure that @@ -20,13 +21,25 @@ export const buttonContainer = style({ background: 'linear-gradient(180deg, rgba(251, 251, 251, 0) 0%, #FBFBFB 25%)', }); -export const containerStyle = style({ - height: `calc(100vh - ${CONTAINER_OFFSET_HEIGHT - OVERLAP_HEIGHT}px - env(safe-area-inset-top))`, - overflow: 'scroll', - msOverflowStyle: 'none', - scrollbarWidth: 'none', - '::-webkit-scrollbar': { - display: 'none', +export const containerStyle = recipe({ + base: { + overflow: 'scroll', + msOverflowStyle: 'none', + scrollbarWidth: 'none', + '::-webkit-scrollbar': { + display: 'none', + }, + }, + variants: { + hasCTAButton: { + true: { + height: `calc(100vh - ${CONTAINER_OFFSET_HEIGHT - OVERLAP_HEIGHT}px - env(safe-area-inset-top))`, + }, + false: { + height: `calc(100vh - env(safe-area-inset-top))`, + paddingBottom: spacings.xl, + }, + }, }, }); diff --git a/apps/bottle/src/models/bottle.ts b/apps/bottle/src/models/bottle.ts index 3129817..0af38e7 100644 --- a/apps/bottle/src/models/bottle.ts +++ b/apps/bottle/src/models/bottle.ts @@ -27,8 +27,8 @@ export interface BaseBottlePreview lastActivatedAt: string; } -export interface RecommendationBottlePreview extends BaseBottlePreview { +export interface RecommendationBottlePreview extends BaseBottlePreview {} + +export interface SentBottlePreview extends BaseBottlePreview { likeEmoji: string; } - -export interface SentBottlePreview extends BaseBottlePreview {} diff --git a/apps/bottle/src/store/query/useRecommendationBottlesQuery.ts b/apps/bottle/src/store/query/useRecommendationBottlesQuery.ts index 0cf8080..3e79c9f 100644 --- a/apps/bottle/src/store/query/useRecommendationBottlesQuery.ts +++ b/apps/bottle/src/store/query/useRecommendationBottlesQuery.ts @@ -1,26 +1,17 @@ import { createInit, GET } from '@/features/server'; import { Tokens } from '@/features/server/auth'; import { getClientSideTokens } from '@/features/server/clientSideTokens'; -import { OtherUser } from '@/models/user'; +import { RecommendationBottlePreview } from '@/models/bottle'; import { useSuspenseQuery, UseSuspenseQueryOptions } from '@tanstack/react-query'; -export interface RecommendationBottlePreview - extends Pick, - Pick { - userId: number; - expiredAt: string; // Date - id: number; - lastActivatedAt: string; - likeEmoji: string; -} - interface RandomBottlesQuery { nextBottleLeftHours: number; randomBottles: RecommendationBottlePreview[]; } export const recommendationBottlesQueryOptions = (tokens: Tokens): UseSuspenseQueryOptions => ({ - queryKey: ['bottles', 'random'], + queryKey: ['bottles', 'recommendation'], + // NOTE: should ALWAYS be stale queryFn: () => GET(`/api/v2/bottles/random`, tokens, createInit(tokens.accessToken)), }); diff --git a/apps/bottle/src/store/query/useSentBottlesQuery.ts b/apps/bottle/src/store/query/useSentBottlesQuery.ts new file mode 100644 index 0000000..3396437 --- /dev/null +++ b/apps/bottle/src/store/query/useSentBottlesQuery.ts @@ -0,0 +1,20 @@ +import { createInit, GET } from '@/features/server'; +import { Tokens } from '@/features/server/auth'; +import { getClientSideTokens } from '@/features/server/clientSideTokens'; +import { SentBottlePreview } from '@/models/bottle'; +import { useSuspenseQuery, UseSuspenseQueryOptions } from '@tanstack/react-query'; + +interface SentBottlesQuery { + sentBottles: SentBottlePreview[]; +} + +export const sentBottlesQueryOptions = (tokens: Tokens): UseSuspenseQueryOptions => ({ + queryKey: ['bottles', 'sent'], + queryFn: () => GET(`/api/v2/bottles/sent`, tokens, createInit(tokens.accessToken)), + // NOTE: should ALWAYS be stale + staleTime: 0, +}); + +export function useSentBottlesQuery() { + return useSuspenseQuery(sentBottlesQueryOptions(getClientSideTokens())); +}