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

fix : 포즈픽 비율 이슈 관련 레이아웃 수정 #43

Merged
merged 9 commits into from
Sep 7, 2023
11 changes: 8 additions & 3 deletions src/apis/apis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,16 @@ export const getPoseDetail = (poseId: number) =>

export const getPoseTalk = () => publicApi.get<PoseTalkResponse>('/pose/talk');

export const getPoseFeed = (peopleCount: number, frameCount: number, tags: string) =>
publicApi.get<PoseFeedResponse>(`/pose`, {
export const getPoseFeed = async (
peopleCount: number,
frameCount: number,
tags: string,
pageNumber: number
) =>
await publicApi.get<PoseFeedResponse>(`/pose`, {
params: {
frameCount,
pageNumber: 0,
pageNumber,
peopleCount,
tags,
},
Expand Down
23 changes: 19 additions & 4 deletions src/apis/queries.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { UseQueryOptions, useQuery } from '@tanstack/react-query';
import {
UseInfiniteQueryOptions,
UseQueryOptions,
useInfiniteQuery,
useQuery,
} from '@tanstack/react-query';

import {
FilterTagsResponse,
Expand Down Expand Up @@ -30,12 +35,22 @@ export const usePoseTalkQuery = (options?: UseQueryOptions<PoseTalkResponse>) =>

export const usePoseFeedQuery = (
{ peopleCount, frameCount, tags }: FilterState,
options?: UseQueryOptions<PoseFeedResponse>
options?: UseInfiniteQueryOptions<PoseFeedResponse>
) =>
useQuery<PoseFeedResponse>(
useInfiniteQuery<PoseFeedResponse>(
['poseFeed', peopleCount, frameCount, tags],
() => getPoseFeed(peopleCount, frameCount, tags.join(',')),
({ pageParam = '' }) => getPoseFeed(peopleCount, frameCount, tags.join(','), pageParam),
{
getNextPageParam: (lastPage) => {
let target = lastPage.filteredContents;
if (lastPage.recommendation) {
target = lastPage.recommendedContents;
} else {
target = lastPage.filteredContents;
}
if (target.last) return false;
return target.number + 1;
},
...options,
}
);
Expand Down
4 changes: 2 additions & 2 deletions src/app/(Main)/feed/components/PhotoList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ interface PhotoList {

export default function PhotoList({ data }: PhotoList) {
return (
<div className="columns-2 overflow-y-scroll py-16">
<>
{data ? (
data.map((item) => (
<Photo
Expand All @@ -20,6 +20,6 @@ export default function PhotoList({ data }: PhotoList) {
) : (
<Photo />
)}
</div>
</>
);
}
39 changes: 30 additions & 9 deletions src/app/(Main)/feed/page.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
'use client';

import Link from 'next/link';
import { useRouter, useSearchParams } from 'next/navigation';
import { useCallback } from 'react';

import EmptyCase from './components/EmptyCase';
import FilterSheet from './components/FilterSheet';
import FilterTab from './components/FilterTab';
import PhotoList from './components/PhotoList';
import { usePoseFeedQuery } from '@/apis';
import { Spacing } from '@/components/Spacing';
import { URL } from '@/constants/url';
import useDidMount from '@/hooks/useDidMount';
import useFilterState from '@/hooks/useFilterState';
import { URL } from '@/constants/url';
import useIntersect from '@/hooks/useObserver';

export default function Feed() {
const params = useSearchParams();
const router = useRouter();

const { filterState, updateFilterState } = useFilterState();
const { data, isFetched } = usePoseFeedQuery(filterState);
const { data, fetchNextPage, hasNextPage, isLoading } = usePoseFeedQuery(filterState);

useDidMount(() => {
if (!params.get('filter')) return;
Expand All @@ -30,25 +31,45 @@ export default function Feed() {
router.replace('/feed');
});

const onIntersect = useCallback(async () => {
if (hasNextPage && !isLoading) {
await fetchNextPage();
}
}, [fetchNextPage, hasNextPage, isLoading]);

const target = useIntersect(onIntersect);

return (
<>
<FilterTab />
<Spacing size={56} />
<div>
{data?.recommendation && (
<Spacing size={40} />
<div className="h-fit overflow-y-scroll">
{data?.pages[0].recommendation ? (
<>
<EmptyCase
title={'신비한 포즈를 찾으시는군요!'}
text={'찾고 싶은 포즈를 저희에게 알려주세요.'}
button={'문의사항 남기기'}
path={URL.inquiry}
/>

<h4 className="mb-16">이런 포즈는 어때요?</h4>
<PhotoList data={data.recommendedContents.content} />
<div className="columns-2 py-16">
{data?.pages.map((page) => (
<PhotoList
key={page.recommendedContents.number}
data={page.recommendedContents.content}
/>
))}
</div>
</>
) : (
<div className="columns-2 py-16">
{data?.pages.map((page) => (
<PhotoList key={page.filteredContents.number} data={page.filteredContents.content} />
))}
</div>
)}
{isFetched ? <PhotoList data={data?.filteredContents.content} /> : <PhotoList />}
<div ref={target} className="h-1" />
</div>
<FilterSheet />
</>
Expand Down
8 changes: 5 additions & 3 deletions src/app/(Main)/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import MainHeader from './components/MainHeader';
import { Spacing } from '@/components/Spacing';
import MainHeader from './components/MainHeader';
import { StrictPropsWithChildren } from '@/types';

export default function MainLayout({ children }: StrictPropsWithChildren) {
return (
<>
<Spacing size={80} />
<MainHeader />
<div className="px-20 py-16">{children}</div>
<div className="flex h-screen flex-col overflow-hidden px-20">
<Spacing size={100} />
{children}
</div>
</>
);
}
23 changes: 9 additions & 14 deletions src/app/(Main)/pick/components/PickSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,28 +33,22 @@ export default function PickSection() {
};

return (
<section className="flex flex-col items-center">
<Spacing size={16} />
<div className="w-full">
<>
<div className="py-16">
<SelectionBasic
data={peopleCountList.slice(1)}
state={countState}
setState={setCountState}
/>
</div>

<Spacing size={16} />

<div className="flex h-460 w-full items-center justify-center bg-black">
<div className="relative flex h-460 w-300 items-center justify-center">
{true && <Lottie loop animationData={lottiePick} play />}
<div className="relative flex flex-1">
<div className="absolute inset-0 flex justify-center bg-black">
{isLoading && <Lottie loop animationData={lottiePick} play />}
<Image
seondal marked this conversation as resolved.
Show resolved Hide resolved
src={image || '/images/image-frame.png'}
fill
alt="sample"
priority
loading="eager"
className={clsx({ hidden: isLoading }, 'cursor-pointer')}
className={clsx({ hidden: isLoading }, 'cursor-pointer object-contain')}
onClick={() =>
open(({ exit }) => (
<Popup>
Expand All @@ -71,17 +65,18 @@ export default function PickSection() {
</Popup>
))
}
alt="이미지"
/>
</div>
</div>

<Spacing size={100} />
<BottomFixedButton
className="bg-main-violet text-white"
onClick={handlePickClick}
disabled={isLoading}
>
{!!image ? '포즈 pick!' : '인원수 선택하고 포즈 pick!'}
</BottomFixedButton>
</section>
</>
);
}
10 changes: 6 additions & 4 deletions src/app/(Main)/talk/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import { Spacing } from '@/components/Spacing';

export default function Talk() {
return (
<div>
<>
<div className="flex flex-1 flex-col items-center justify-center">
<TitleSection />
<TalkSection />
</div>
<Spacing size={80} />
<TitleSection />
<TalkSection />
</div>
</>
);
}
10 changes: 6 additions & 4 deletions src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,18 @@
display: none;
}

html {
font-size: calc(16vw / 440 * 100);
}

@media (min-width: 440px) {
html {
font-size: 16px;
}
}

@supports (-webkit-touch-callout: none) {
.h-screen {
height: -webkit-fill-available;
}
}

h1 {
font-weight: 700;
font-size: 3rem;
Expand Down
5 changes: 4 additions & 1 deletion src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const DEFAULT_OG_IMAGE = '/images/main_star.png';
export const metadata: Metadata = {
metadataBase: new URL(BASE_SITE_URL),
title: {
template: `${DEFAULT_OG_TITLE} / %s `, // 요건 뭔가용?
template: DEFAULT_OG_TITLE,
default: DEFAULT_OG_TITLE,
},
description: DEFAULT_OG_DESC,
Expand All @@ -39,6 +39,9 @@ export const metadata: Metadata = {
maximumScale: 1,
userScalable: false,
},
icons: {
icon: './favicon.ico',
},
manifest: '/manifest.json',
themeColor: '#ffffff',
};
Expand Down
16 changes: 16 additions & 0 deletions src/hooks/useObserver.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { useEffect, useRef } from 'react';

const useIntersect = (callback: () => void, options?: IntersectionObserverInit) => {
const target = useRef(null);

useEffect(() => {
if (!target.current) return;
const observer = new IntersectionObserver(callback, options);
observer.observe(target.current);
return () => observer.disconnect();
}, [callback, options]);

return target;
};

export default useIntersect;