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

홈 페이지 API 연동 #283

Merged
merged 10 commits into from
Dec 17, 2024
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
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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

나현님, 해당 파일은 3개의 컴포넌트로 구성되어 있는데 컨벤션을 조금 수정하면 좋을 것 같습니다. 👀

  1. 파일이름(HomeRecommendedLists) export 컴포넌트(TrendingList) 일치
  2. export 컴포넌트(TrendingList)의 export default 코드를 TrendingList 컴포넌트에 위치 (지금은 TrendingListItem 컴포넌트에 위치한것 같아요)

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 && (
Comment on lines 43 to +44
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

한가지 궁금증이 혹시 추천리스트가 없을때는 무엇을 보여주는 것인가요?! 아니면 해당 API는 반드시 리스폰스(=리스트)가 존재하나요?! 👀

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

스켈레톤을 보여주어야 하는데 이 부분은 시간이 부족하여 작업을 하지 못했습니다 ㅠㅠ 추후 리팩토링 시 작업하겠습니다!

<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
Loading