Skip to content

Commit

Permalink
홈 페이지 API 연동 (#283)
Browse files Browse the repository at this point in the history
* Feat: 트렌딩 리스트 api 연결

* Feat: 이 주제로 만들어주세요 api 연결

* Chore: 추천 리스트 css 파일명 변경

* Fix: topic api 연동 type 수정 및 사용자 추천 로직 개선

* Feat: 검색바 구현

* Style: 필요없는 코드 정리

* Fix: 코드리뷰 반영

* Fix: 불필요한 Link 태그 제거

* Fix: ci 에러 해결
  • Loading branch information
Nahyun-Kang authored Dec 17, 2024
1 parent 15e6086 commit c91bf53
Show file tree
Hide file tree
Showing 34 changed files with 4,683 additions and 4,947 deletions.
5 changes: 5 additions & 0 deletions src/app/(home)/_components/FeedLists.css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ import { vars } from '@/styles/__theme.css';

export const listBackground = createVar();

export const listItemWrapper = style({
cursor: 'pointer',
});

export const wrapperOuter = style({
padding: '0 16px 84px 16px',
marginTop: '12px',
Expand Down Expand Up @@ -112,6 +116,7 @@ export const profileImageWrapper = style({
height: '30px',

position: 'relative',
cursor: 'pointer',
});

export const ownerProfileImage = style({
Expand Down
19 changes: 10 additions & 9 deletions src/app/(home)/_components/FeedLists.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import Link from 'next/link';
import { useInfiniteQuery } from '@tanstack/react-query';
import { useMemo } from 'react';
import { assignInlineVars } from '@vanilla-extract/dynamic';
import { useRouter } from 'next/navigation';

import SimpleList from '@/components/SimpleList/SimpleList';
import getRecentLists from '@/app/_api/home/getRecentLists';
Expand All @@ -14,13 +15,13 @@ import useIntersectionObserver from '@/hooks/useIntersectionObserver';
import * as styles from './FeedLists.css';
import { exploreBackgroundColors } from '@/lib/constants/exploreListBackgroundColor';
import fallbackProfile from '/public/images/fallback_profileImage.webp';
import { LIST_DATA as feedLists } from '@/app/(home)/mock/mockdata';
import NoDataComponent from '@/components/NoData/NoDataComponent';
import NoDataButton from '@/components/NoData/NoDataButton';

import { commonLocale } from '@/components/locale';
import { useLanguage } from '@/store/useLanguage';
import { useTab } from '@/store/useTab';
import useMoveToPage from '@/hooks/useMoveToPage';

interface FeedListsType {
category?: string;
Expand All @@ -30,6 +31,7 @@ interface FeedListsType {
function FeedLists({ category, tab = 'recent' }: FeedListsType) {
const current_QueryKey = tab === 'recent' ? [QUERY_KEYS.getRecentLists, category] : [QUERY_KEYS.getFollowingLists];
const { setCurrentTab } = useTab();
const { onClickMoveToPage } = useMoveToPage();

//리스트 무한스크롤 리액트 쿼리 함수
const {
Expand Down Expand Up @@ -83,11 +85,9 @@ function FeedLists({ category, tab = 'recent' }: FeedListsType) {
{feedLists && feedLists?.length !== 0 ? (
feedLists?.map((item, index) => {
return (
<Link href={`/list/${item.id}`} key={item.id}>
<li>
<FeedListItem item={item} index={index} />
</li>
</Link>
<li key={item.id} onClick={onClickMoveToPage(`/list/${item.id}`)} className={styles.listItemWrapper}>
<FeedListItem item={item} index={index} />
</li>
);
})
) : (
Expand Down Expand Up @@ -117,6 +117,7 @@ interface FeedListItemType {

function FeedListItem({ item, index }: FeedListItemType) {
const { language } = useLanguage();
const { onClickMoveToPage } = useMoveToPage();

const COLOR_INDEX = (num: number) => num % 5;

Expand All @@ -126,8 +127,8 @@ function FeedListItem({ item, index }: FeedListItemType) {
style={assignInlineVars({ [styles.listBackground]: exploreBackgroundColors[COLOR_INDEX(index)] })}
>
<div className={styles.listTopWrapper}>
<div className={styles.ownerInformationWrapper}>
<Link href={`/user/${item.ownerId}/mylist`} className={styles.profileImageWrapper}>
<div className={styles.ownerInformationWrapper} onClick={onClickMoveToPage(`/user/${item.ownerId}/mylist`)}>
<div className={styles.profileImageWrapper}>
{item?.ownerProfileImage ? (
<Image
src={item.ownerProfileImage}
Expand All @@ -151,7 +152,7 @@ function FeedListItem({ item, index }: FeedListItemType) {
sizes="100vw 100vh"
/>
)}
</Link>
</div>
<div className={styles.ownerNicknameText}>{item.ownerNickname}</div>
</div>
<div className={styles.version}>{`업데이트 ${item.updateCount}회째`}</div>
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion src/app/(home)/_components/Header.css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export const headerWrapper = style({
width: '100%',
height: '40px',
padding: '10px 16px',
margin: '0 0 12px',
margin: '0 0 16px',
});

export const entireWrapper = style({
Expand Down
12 changes: 8 additions & 4 deletions src/app/(home)/_components/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import Link from 'next/link';
import Image from 'next/image';
import { useQuery } from '@tanstack/react-query';

import SearchBarComponent from '@/components/SearchBar';
import SearchBarArea from './SearchBarArea';
import Modal from '@/components/Modal/Modal';
import LoginModal from '@/components/login/LoginModal';

Expand All @@ -24,7 +24,11 @@ import BellIcon from '/public/icons/ver3/bell.svg';
import Avatar from '/public/icons/ver3/Avatar.svg';

function Header() {
const { isOn: isSearchBarOpened, handleSetOn: handleSearchBarOpened } = useBooleanOutput();
const {
isOn: isSearchBarOpened,
handleSetOn: handleSearchBarOpened,
handleSetOff: handleSearchBarClosed,
} = useBooleanOutput();
const { isOn, handleSetOn, handleSetOff } = useBooleanOutput();
const [isLoggedIn, setIsLoggedIn] = useState(false); // 로그인 상태를 관리하는 useState 추가

Expand All @@ -41,7 +45,7 @@ function Header() {
};

const handleInactivateSearchBar = () => {
handleSearchBarOpened();
handleSearchBarClosed();
};

const handleSearchIconClick = () => {
Expand All @@ -55,7 +59,7 @@ function Header() {

return (
<header className={styles.headerWrapper}>
{isSearchBarOpened && <SearchBarComponent handleCancel={handleInactivateSearchBar} />}
{isSearchBarOpened && <SearchBarArea handleCancel={handleInactivateSearchBar} />}
{!isSearchBarOpened && (
<div className={styles.entireWrapper}>
<div className={styles.homeTitleContainer}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,18 @@ import { Swiper, SwiperSlide } from 'swiper/react';
import 'swiper/css';
import { Autoplay, EffectCoverflow } from 'swiper/modules';

import getTrendingLists from '@/app/_api/home/getTrendingLists';
import getHomeRecommendedLists from '@/app/_api/home/getHomeRecommendedLists';
import { QUERY_KEYS } from '@/lib/constants/queryKeys';
import { TrendingListType } from '@/lib/types/exploreType';
import { TRENDINGLISTS_DATA } from '../mock/mockdata';
import { HomeRecommendedListType } from '@/lib/types/homeType';

import * as styles from './TrendingLists.css';
import * as styles from './HomeRecommendedLists.css';
import { vars } from '@/styles/theme.css';
import { TrendingListsSkeleton } from '../../../components/exploreComponents/Skeleton';

function TrendingList() {
// 오류로인해 주석처리 해 둠
// const { data: trendingLists, isFetching } = useQuery({
// queryKey: [QUERY_KEYS.getTrendingLists],
// queryFn: () => getTrendingLists(),
// });
function HomeRecommendedLists() {
const { data: recommendedLists, isFetching } = useQuery({
queryKey: [QUERY_KEYS.getHomeRecommendedLists],
queryFn: () => getHomeRecommendedLists(),
});

const SWIPER_STYLE = useMemo(
() => ({
Expand All @@ -40,15 +37,11 @@ function TrendingList() {
[]
);

// if (isFetching) {
// return <TrendingListsSkeleton />;
// }

return (
<section className={styles.wrapper}>
<div className={styles.listWrapper}>
<div className={styles.slide}>
{TRENDINGLISTS_DATA && TRENDINGLISTS_DATA.length > 0 && (
{recommendedLists && recommendedLists.length > 0 && (
<Swiper
slidesPerView={'auto'}
grabCursor={true}
Expand All @@ -63,9 +56,9 @@ function TrendingList() {
className="mySwiper"
style={SWIPER_STYLE}
>
{TRENDINGLISTS_DATA.map((item, index) => (
{recommendedLists.map((item, index) => (
<SwiperSlide key={index} className={styles.sliderItem} style={SWIPER_SLIDER_STYLE}>
<TrendingListItem item={item} index={index} />
<RecommendedListsItem item={item} index={index} />
</SwiperSlide>
))}
</Swiper>
Expand All @@ -76,12 +69,14 @@ function TrendingList() {
);
}

export default HomeRecommendedLists;

interface TrendingListItemProps {
item: any;
item: HomeRecommendedListType;
index: number;
}

function TrendingListItem({ item }: TrendingListItemProps) {
function RecommendedListsItem({ item }: TrendingListItemProps) {
if (!item) return null;

return (
Expand All @@ -95,7 +90,7 @@ function TrendingListItem({ item }: TrendingListItemProps) {
[styles.customBorderRadius]: '50%',
})}
>
<TrendingListInformation item={item} />
<RecommendedListsInfo item={item} />
</div>
) : (
<div
Expand All @@ -105,22 +100,20 @@ function TrendingListItem({ item }: TrendingListItemProps) {
[styles.customBackgroundColor]: '#ffffff',
})}
>
<TrendingListInformation item={item} />
<RecommendedListsInfo item={item} />
</div>
)}
</div>
</Link>
);
}

export default TrendingList;

interface TrendingListInformationType {
item?: TrendingListType;
interface RecommendedListsInfoType {
item?: HomeRecommendedListType;
}

function TrendingListInformation({ item }: TrendingListInformationType) {
if (!item) return null; // item이 없으면 null을 반환하여 렌더링을 중지합니다.
function RecommendedListsInfo({ item }: RecommendedListsInfoType) {
if (!item) return null;

return (
<div className={styles.itemInformationWrapper}>
Expand All @@ -133,11 +126,12 @@ function TrendingListInformation({ item }: TrendingListInformationType) {
<p className={styles.listOwner}>{item.ownerNickname}</p>
</div>
<ul className={styles.top3Wrapper}>
{item.top3.map((el, idx) => (
<li key={idx} className={item.itemImageUrl ? styles.top3ItemWithImage : styles.top3ItemNoImage}>
{`${idx + 1}. ${el.title}`}
</li>
))}
{item &&
item?.items?.map((el, idx) => (
<li key={idx} className={item.itemImageUrl ? styles.top3ItemWithImage : styles.top3ItemNoImage}>
{`${idx + 1}. ${el.title}`}
</li>
))}
</ul>
</div>
);
Expand Down
6 changes: 3 additions & 3 deletions src/app/(home)/_components/RecommendationFeed.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import UsersRecommendation from '@/components/exploreComponents/RecommendedUsers';
import UsersRecommendation from '@/app/(home)/_components/RecommendedUsers';
import TopicsRecommendation from '@/app/(home)/_components/TopicsRecommendation';
import TrendingList from '@/app/(home)/_components/TrendingLists';
import HomeRecommendedLists from '@/app/(home)/_components/HomeRecommendedLists';

function RecommendationFeed() {
return (
<>
<TrendingList />
<HomeRecommendedLists />
<TopicsRecommendation />
<UsersRecommendation />
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import { commonLocale } from '@/components/locale';
import { useLanguage } from '@/store/useLanguage';

function UsersRecommendation() {
const { language } = useLanguage();
//zustand로 관리하는 user정보 불러오기
const { user: userMe } = useUser();
const myId = userMe.id;
Expand All @@ -26,7 +25,6 @@ function UsersRecommendation() {
const { data: usersList, isFetching } = useQuery<UserProfileType[]>({
queryKey: [QUERY_KEYS.getRecommendedUsers],
queryFn: () => getRecommendedUsers(),
enabled: userMe && !!myId,
retry: 1,
});

Expand All @@ -39,17 +37,17 @@ function UsersRecommendation() {
}
};

if (!userMe) {
return null;
}
// if (!userMe) {
// return null;
// }

return (
<section>
{isFetching ? (
<UserListsSkeleton />
) : (
<>
{myId && usersList?.length !== 0 && (
{usersList && usersList?.length !== 0 && (
<div className={styles.wrapper}>
<div className={styles.titleWrapper}>
<h2 className={styles.sectionTitle}>추천 리스터</h2>
Expand All @@ -61,7 +59,7 @@ function UsersRecommendation() {
<UserRecommendListItem
data={item}
handleScrollToRight={handleScrollToRight}
userId={userMe?.id}
userId={userMe?.id as number}
/>
</li>
);
Expand Down Expand Up @@ -93,8 +91,10 @@ function UserRecommendListItem({ data, handleScrollToRight, userId }: UserRecomm
};

const handleFollowButtonClick = () => {
handleFollowingState();
handleScrollToRight();
if (userId) {
handleFollowingState();
handleScrollToRight();
}
};

return (
Expand Down
35 changes: 35 additions & 0 deletions src/app/(home)/_components/SearchBarArea.css.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { style } from '@vanilla-extract/css';

export const wrapper = style({
width: '100%',

display: 'flex',
alignItems: 'center',
});

export const inputWrapper = style({
width: '100%',

display: 'flex',
alignItems: 'center',
});

export const input = style({
width: '100%',

fontSize: '1.6rem',
overflow: 'hidden',
'::placeholder': {
color: '#637587',
fontWeight: '400',
fontSize: '1.6rem',
},
});

export const cancelButton = style({
flexShrink: 0,
fontWeight: '400',
fontSize: '1.6rem',
letterSpacing: '-3%',
color: '#213752',
});
Loading

0 comments on commit c91bf53

Please sign in to comment.