Skip to content

Commit

Permalink
Merge pull request #105 from YAPP-Github/feature/FE-069
Browse files Browse the repository at this point in the history
Feature/fe-069 메인페이지 반응형 적용 및 필터 추가
  • Loading branch information
sxungchxn authored Jul 22, 2023
2 parents fcb0515 + b39d55c commit 121cb28
Show file tree
Hide file tree
Showing 45 changed files with 903 additions and 91 deletions.
6 changes: 6 additions & 0 deletions public/sprite.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions public/spriteIcons/lightning.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions public/spriteIcons/pluswhite.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions public/spriteIcons/samsung.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
23 changes: 20 additions & 3 deletions src/api/board/api.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,27 @@
import { request } from '@/utils/ky/request';
import { BOARDS_PER_PAGE } from '@/app/home/constants';
import { BoardListPagingData, BoardListResponse, BoardDetail } from './types';
import { BoardListPagingData, BoardListResponse, BoardDetail, BoardRegionResponse } from './types';

class BoardAPI {
/**
* board list를 페이지당 boardsPerPage 개수만큼 가져옵니다.
* @param requestlastId - 마지막으로 가져온 board의 id
* @param boardsPerPage - 페이지당 가져올 board 개수
* @param cityId - 가져올 board의 cityId
* @param provinceId - 가져올 board의 provinceId
*/
async getBoardList(requestlastId?: number, boardsPerPage = BOARDS_PER_PAGE): Promise<BoardListPagingData> {
const { list, lastId } = await request('v1/boards', {
async getBoardList(
requestlastId?: number,
boardsPerPage = BOARDS_PER_PAGE,
cityId?: number,
provinceId?: number,
): Promise<BoardListPagingData> {
const { list, lastId } = await request('v2/boards', {
searchParams: {
countPerScroll: boardsPerPage,
...(requestlastId && { lastId: requestlastId }),
...(cityId && { cityId }),
...(provinceId && { provinceId }),
},
}).json<BoardListResponse>();

Expand Down Expand Up @@ -54,6 +63,14 @@ class BoardAPI {
async deleteBoard(boardId: number) {
return request.delete(`v1/boards/${boardId}`).json();
}

/**
* 먹팟 게시글들의 지역 카테고리 목록을 조회합니다.
*/
async getBoardRegions() {
const { list } = await request.get(`v1/boards/regions`).json<BoardRegionResponse>();
return list;
}
}

// api fetchers instance
Expand Down
2 changes: 2 additions & 0 deletions src/api/board/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ export { default as useJoinBoard } from './useJoinBoard';
export { default as useCancelJoinBoard } from './useCancelJoinBoard';

export { default as useDeleteBoard } from './useDeleteBoard';

export { default as useBoardRegions } from './useBoardRegions';
8 changes: 5 additions & 3 deletions src/api/board/hooks/useBoardListQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ import { boardAPI } from '@/api/board/api';
/**
* board list를 페이지당 boardsPerPage 개수만큼 가져옵니다.
* @param boardsPerPage 페이지 당 한 번에 가져올 board 개수
* @param cityId 가져올 board의 cityId
* @param provinceId 가져올 board의 provinceId
*/
const useBoardListQuery = (boardsPerPage = BOARDS_PER_PAGE) => {
const useBoardListQuery = (boardsPerPage = BOARDS_PER_PAGE, cityId?: number, provinceId?: number) => {
const { data, isFetchingNextPage, hasNextPage, fetchNextPage, ...rest } =
useSuspenseInfiniteQuery<BoardListPagingData>(
boardKeys.list(),
({ pageParam = undefined }) => boardAPI.getBoardList(pageParam, boardsPerPage),
boardKeys.list(cityId, provinceId),
({ pageParam = undefined }) => boardAPI.getBoardList(pageParam, boardsPerPage, cityId, provinceId),
{
getNextPageParam: (lastPage) => (lastPage.isLastPage ? undefined : lastPage.lastId),
},
Expand Down
7 changes: 7 additions & 0 deletions src/api/board/hooks/useBoardRegions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { useSuspenseQuery } from '@suspensive/react-query';
import { boardAPI } from '@/api/board/api';
import { boardKeys } from '@/api/board/queryKeys';

const useBoardRegions = () => useSuspenseQuery(boardKeys.regions(), () => boardAPI.getBoardRegions());

export default useBoardRegions;
3 changes: 2 additions & 1 deletion src/api/board/queryKeys.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export const boardKeys = {
all: ['board'] as const,
list: () => [...boardKeys.all, 'list'] as const,
list: (cityId?: number, provinceId?: number) => [...boardKeys.all, 'list', cityId, provinceId] as const,
detail: (boardId: number) => [...boardKeys.all, 'detail', boardId] as const,
regions: () => [...boardKeys.all, 'regions'] as const,
};
17 changes: 17 additions & 0 deletions src/api/board/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,20 @@ export interface BoardDetail {
views: number;
participants: Profile[];
}

export interface BoardProvince {
provinceId: number;
provinceName: string;
sumByProvince: number;
}

export interface BoardRegion {
cityId: number;
cityName: string;
sumByCity: number;
provinces: BoardProvince[];
}

export interface BoardRegionResponse {
list: BoardRegion[];
}
33 changes: 30 additions & 3 deletions src/app/error.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,34 @@
'use client';

const error = () => {
return <div>error</div>;
import { Header } from '@/components/server';
import { useIsMobile } from '@/hooks';
import { BottomButton, Button, Content, ErrorMessage } from '@/components';
import { useRouter } from 'next/navigation';

const ErrorPage = ({ reset }: { reset: () => void }) => {
const router = useRouter();
const isMobile = useIsMobile();

const handleClickRetry = () => {
reset();
router.push('/');
};

return (
<>
<Header actionRequired={false} />
<Content>
<ErrorMessage title="에러가 발생했습니다." subTitle="다시 한번 시도해 주세요.">
{!isMobile && (
<Button size="large" onClick={handleClickRetry}>
홈으로 돌아가기
</Button>
)}
<BottomButton onClick={handleClickRetry}>홈으로 돌아가기</BottomButton>
</ErrorMessage>
</Content>
</>
);
};

export default error;
export default ErrorPage;
45 changes: 42 additions & 3 deletions src/app/home/components/BoardCard/BoardCard.css.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { style } from '@vanilla-extract/css';
import { recipe } from '@vanilla-extract/recipes';
import { themeTokens } from '@/styles/theme.css';
import { screenMQ, themeTokens } from '@/styles/theme.css';
import { sizeProp } from '@/utils/sizeProp';
import { fontVariant } from '@/styles/variant.css';

const { space, borderRadius, color } = themeTokens;

Expand All @@ -9,8 +11,7 @@ export const wrapper = recipe({
padding: space['3xl'],
borderRadius: borderRadius.xl,
border: `1px solid ${color.grey200}`,
width: '364px',
height: '324px',
width: sizeProp('364px'),
position: 'relative',
transitionProperty: 'box-shadow, transform',
transitionDuration: '0.2s',
Expand All @@ -21,6 +22,13 @@ export const wrapper = recipe({
transform: `translateY(-8px)`,
},
},

'@media': {
[screenMQ.m]: {
width: sizeProp('312px'),
padding: space.xl,
},
},
},
variants: {
isRecruiting: {
Expand Down Expand Up @@ -51,11 +59,29 @@ export const chips = style({
gap: space.sm,
});

export const timeText = style({
...fontVariant.body2,
color: color.sub,

'@media': {
[screenMQ.m]: {
...fontVariant.body3,
},
},
});

export const titleStyle = style({
...fontVariant.title1,
whiteSpace: 'nowrap',
overflow: 'hidden',
textOverflow: 'ellipsis',
marginBottom: space.xl,

'@media': {
[screenMQ.m]: {
...fontVariant.title3,
},
},
});

export const body = style({
Expand All @@ -75,6 +101,13 @@ export const body = style({
bottom: 0,
},
},

'@media': {
[screenMQ.m]: {
paddingBottom: space.lg,
marginBottom: space.lg,
},
},
});

export const bodyItem = style({
Expand Down Expand Up @@ -105,4 +138,10 @@ export const participantsList = style({
display: 'flex',
alignItems: 'center',
gap: space.md,

'@media': {
[screenMQ.m]: {
display: 'none',
},
},
});
5 changes: 2 additions & 3 deletions src/app/home/components/BoardCard/BoardCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
wrapper,
header,
chips,
timeText,
titleStyle,
body,
bodyItem,
Expand Down Expand Up @@ -50,9 +51,7 @@ const BoardCard = ({ boardListItem }: Props) => {
<Chip color={getChipColor(status)}>{status}</Chip>
{todayOrTomorrow && <Chip color={getChipColor(todayOrTomorrow)}>{todayOrTomorrow}</Chip>}
</div>
<Typography variant="label2" color="sub">
{elapsedTime}
</Typography>
<span className={timeText}>{elapsedTime}</span>
</div>
<Typography className={titleStyle} variant="title1" color="primary">
{title}
Expand Down
21 changes: 20 additions & 1 deletion src/app/home/components/BoardCardList/BoardCardList.css.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,29 @@
import { style } from '@vanilla-extract/css';
import { themeTokens } from '@/styles/theme.css';
import { screenMQ, themeTokens } from '@/styles/theme.css';

const { space } = themeTokens;

export const listGrid = style({
display: 'grid',
gridTemplateColumns: '1fr 1fr',
gap: space['2xl'],

'@media': {
[screenMQ.m]: {
padding: `0 ${space['2xl']}`,
justifyContent: 'center',
gridTemplateColumns: '1fr',
gap: space['md'],
},
},
});

export const noBoard = style({
flexGrow: 1,
height: '100%',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
flexDirection: 'column',
gap: space.lg,
});
23 changes: 19 additions & 4 deletions src/app/home/components/BoardCardList/BoardCardList.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,40 @@
'use client';

import { SvgIcon, Typography } from '@/components';
import { useIntersectObserver } from '@/hooks';
import { useBoardListQuery } from '@/api/hooks';
import { BoardCard } from '@/app/home/components';
import { BOARDS_PER_PAGE } from '@/app/home/constants';
import { useRegionsFilterStore } from '@/app/home/store';
import { listGrid, noBoard } from './BoardCardList.css';

const BoardCardList = () => {
const { data: boardList, getNextPage } = useBoardListQuery(BOARDS_PER_PAGE);
const { cityId, provinceId } = useRegionsFilterStore((state) => ({
cityId: state.cityId,
provinceId: state.provinceId,
}));

const { data: boardList, getNextPage } = useBoardListQuery(BOARDS_PER_PAGE, cityId, provinceId);

const [ref] = useIntersectObserver<HTMLDivElement>({
rootMargin: '100px',
onIntersect: getNextPage,
});

return (
<>
return boardList.length > 0 ? (
<ul className={listGrid}>
{boardList.map((boardListItem) => (
<BoardCard key={boardListItem.boardId} boardListItem={boardListItem} />
))}
<div ref={ref}></div>
</>
</ul>
) : (
<div className={noBoard}>
<SvgIcon id="info" width={40} height={40} />
<Typography variant="body2" as="p" color="hint">
검색 결과가 없습니다.
</Typography>
</div>
);
};

Expand Down
Loading

0 comments on commit 121cb28

Please sign in to comment.