Skip to content

Commit

Permalink
Merge pull request #67 from epigram5-9/feat/FE-17
Browse files Browse the repository at this point in the history
FE-17 ✨ 최근 에피그램 더보기 기능 구현
  • Loading branch information
newjinlee authored Jul 24, 2024
2 parents ba3c127 + 9068f87 commit f013f30
Show file tree
Hide file tree
Showing 11 changed files with 108 additions and 51 deletions.
2 changes: 2 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ module.exports = {
'react/jsx-props-no-spreading': 'off',
'no-use-before-define': 'off',
'@typescript-eslint/no-use-before-define': ['off'],
"react/require-default-props": 'off',
"react/self-closing-comp": 'off',
},
settings: {
react: {
Expand Down
6 changes: 6 additions & 0 deletions public/icon/plus-icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions src/apis/getRecentEpigrams.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import type { GetRecentEpigramsResponseType } from '@/schema/recentEpigram';
import httpClient from './index';

const getRecentEpigrams = async (): Promise<GetRecentEpigramsResponseType> => {
const getRecentEpigrams = async (limit: number): Promise<GetRecentEpigramsResponseType> => {
const response = await httpClient.get('/epigrams', {
params: {
limit: 3,
limit,
},
});
return response.data;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
/*
1개의 감정 아이콘 카드를 랜더링 합니다.
아이콘의 타입, 상태, 크기, 클릭 이벤트를 관리합니다.
아이콘 타입과 상태에 따라 아이콘의 모양과 스타일을 조정합니다.
*/

import React from 'react';
import cn from '@/lib/utils';
import Image from 'next/image';
Expand Down Expand Up @@ -104,11 +110,4 @@ function EmotionIconCard({ iconType = '감동', state = 'Default', size = 'sm',
);
}

EmotionIconCard.displayName = 'EmotionIconCard';

// 기본 props 설정
EmotionIconCard.defaultProps = {
onClick: () => {},
};

export default EmotionIconCard;
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
/*
여러 개의 EmotionIconCard를 관리합니다.
사용자 인터페이스에 필요한 상호 작용 로직을 포함합니다.
*/

import React, { useState } from 'react';
import InteractiveEmotionIconCard from '@/components/Emotion/card/InteractiveEmotionIconCard';
import EmotionIconCard from '@/components/Emotion/EmotionCard';
import useMediaQuery from '@/hooks/useMediaQuery';
import { EmotionType, EmotionState } from '@/types/EmotionTypes';

Expand Down Expand Up @@ -52,7 +57,7 @@ function EmotionSelector() {
return (
<div className={`justify-start items-start inline-flex ${containerClass}`}>
{(['감동', '기쁨', '고민', '슬픔', '분노'] as const).map((iconType) => (
<InteractiveEmotionIconCard key={iconType} iconType={iconType} size={cardSize} state={states[iconType]} onClick={() => handleCardClick(iconType)} />
<EmotionIconCard key={iconType} iconType={iconType} size={cardSize} state={states[iconType]} onClick={() => handleCardClick(iconType)} />
))}
</div>
);
Expand Down
12 changes: 0 additions & 12 deletions src/components/Emotion/card/InteractiveEmotionIconCard.tsx

This file was deleted.

32 changes: 22 additions & 10 deletions src/components/Header/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,35 @@
import React from 'react';
import { useRouter } from 'next/router';
import Image from 'next/image';
import { HeaderProps } from '../../types/Header';
import { useToast } from '../ui/use-toast';
import LOGO_ICON from '../../../public/epigram-icon.png';
import ARROW_LEFT_ICON from '../../../public/icon/arrow-left-icon.svg';
import PROFILE_ICON from '../../../public/icon/profile-icon.svg';
import SEARCH_ICON from '../../../public/icon/search-icon.svg';
import SHARE_ICON from '../../../public/icon/share-icon.svg';

// TODO 네비게이션 바를 나타내는 컴포넌트 입니다.
// TODO 상위 컴포넌트에서 Props를 받아 원하는 스타일을 보여줍니다.
// TODO 사용 예시
// TODO <Header icon='back' routerPage='원하는 페이지 주소' isLogo={false} insteadOfLogo='센터 텍스트' isProfileIcon={false} isShareIcon={false} isButton textInButton='버튼 텍스트' disabled={false} onClick={동작할 함수} />
// TODO <Header icon='search' routerPage='/search' isLogo insteadOfLogo='' isProfileIcon isShareIcon={false} isButton={false} textInButton='' disabled={false} onClick={() => {}} />;
// TODO icon: 'back'을 사용할 경우 routerPage의 값을 무조건 지정해줘야 합니다.
// TODO isLogo={false}일 경우 insteadOfLogo의 값을 무조건 지정해줘야 합니다.
// TODO isButton 일 경우 textInButton의 값을 무조건 지정해줘야 합니다.
// TODO SHARE_ICON 추가 시 토스트 기능도 사용하려면 해당 컴포넌트 아래 <Toaster /> 를 추가해주세요.
// NOTE 네비게이션 바를 나타내는 컴포넌트 입니다.
// NOTE 상위 컴포넌트에서 Props를 받아 원하는 스타일을 보여줍니다.
// NOTE 사용 예시
// NOTE <Header icon='back' routerPage='원하는 페이지 주소' isLogo={false} insteadOfLogo='센터 텍스트' isProfileIcon={false} isShareIcon={false} isButton textInButton='버튼 텍스트' disabled={false} onClick={동작할 함수} />
// NOTE <Header icon='search' routerPage='/search' isLogo insteadOfLogo='' isProfileIcon isShareIcon={false} isButton={false} textInButton='' disabled={false} onClick={() => {}} />;
// NOTE icon: 'back'을 사용할 경우 routerPage의 값을 무조건 지정해줘야 합니다.
// NOTE isLogo={false}일 경우 insteadOfLogo의 값을 무조건 지정해줘야 합니다.
// NOTE isButton 일 경우 textInButton의 값을 무조건 지정해줘야 합니다.
// NOTE SHARE_ICON 추가 시 토스트 기능도 사용하려면 해당 컴포넌트 아래 <Toaster /> 를 추가해주세요.

export interface HeaderProps {
icon: 'back' | 'search' | '';
routerPage: string;
isLogo: boolean;
insteadOfLogo: string;
isProfileIcon: boolean;
isShareIcon: boolean;
isButton: boolean;
textInButton: string;
disabled: boolean;
onClick: (e: React.MouseEvent<HTMLButtonElement>) => void;
}

function Header({ isLogo, icon, insteadOfLogo, isButton, isProfileIcon, isShareIcon, textInButton, routerPage, disabled, onClick }: HeaderProps) {
const router = useRouter();
Expand Down
29 changes: 29 additions & 0 deletions src/components/main/LoadMoreButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React from 'react';
import Image from 'next/image';

interface LoadMoreButtonProps {
onClick: () => void;
}

function LoadMoreButton({ onClick }: LoadMoreButtonProps) {
return (
<div
onClick={onClick}
className='h-12 px-[18px] py-3 rounded-[100px] border border-[#cfdbea] justify-center items-center gap-1 inline-flex cursor-pointer'
role='button'
tabIndex={0}
onKeyPress={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
onClick();
}
}}
>
<div className='w-6 h-6 relative'>
<Image src='/icon/plus-icon.svg' alt='plus icon' layout='fill' objectFit='contain' />
</div>
<div className='text-#abb8ce text-sm font-normal font-Pretendard leading-normal'>더보기</div>
</div>
);
}

export default LoadMoreButton;
34 changes: 31 additions & 3 deletions src/components/main/RecentEpigram.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,45 @@
import React from 'react';
import React, { useState } from 'react';
import { useRouter } from 'next/router';
import useGetRecentEpigrams from '@/hooks/useGetRecentEpigrams';
import EpigramCard from '@/components/Card/EpigramCard';
import { RecentEpigramType } from '@/schema/recentEpigram';
import LoadMoreButton from './LoadMoreButton';

function RecentEpigrams() {
const { data, error, isLoading } = useGetRecentEpigrams();
const router = useRouter();
const [limit, setLimit] = useState(3);
const { data, error, isLoading } = useGetRecentEpigrams(limit);

const handleEpigramClick = (id: number) => {
router.push(`/epigrams/${id}`);
};

const loadMore = () => {
setLimit((prevLimit) => prevLimit + 5);
};

if (isLoading) return <p>로딩 중...</p>;
if (error) return <p>{error.message}</p>;

return (
<div>
<h1>최신 에피그램</h1>
{data?.list.map((epigram) => <EpigramCard key={epigram.id} content={epigram.content} author={epigram.author} tags={epigram.tags} />)}
{data?.list.map((epigram: RecentEpigramType) => (
<div
key={epigram.id}
onClick={() => handleEpigramClick(epigram.id)}
role='button'
tabIndex={0}
onKeyPress={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
handleEpigramClick(epigram.id);
}
}}
>
<EpigramCard content={epigram.content} author={epigram.author} tags={epigram.tags} />
</div>
))}
{data && limit < data.totalCount && <LoadMoreButton onClick={loadMore} />}
</div>
);
}
Expand Down
6 changes: 3 additions & 3 deletions src/hooks/useGetRecentEpigrams.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import { useQuery } from '@tanstack/react-query';
import getRecentEpigrams from '@/apis/getRecentEpigrams';
import { GetRecentEpigramsResponseType } from '@/schema/recentEpigram';

const useGetRecentEpigrams = () =>
const useGetRecentEpigrams = (limit: number) =>
useQuery<GetRecentEpigramsResponseType, Error>({
queryKey: ['recentEpigrams', 3],
queryFn: getRecentEpigrams,
queryKey: ['recentEpigrams', limit],
queryFn: () => getRecentEpigrams(limit),
});

export default useGetRecentEpigrams;
12 changes: 0 additions & 12 deletions src/types/Header.ts

This file was deleted.

0 comments on commit f013f30

Please sign in to comment.