Skip to content

Commit

Permalink
Merge pull request #106 from P1Z7/feat/my-artist-event-api
Browse files Browse the repository at this point in the history
✨ feat: 아티스트의 행사 api 연결, 💄 design: 데스크탑 디자인 수정
  • Loading branch information
gw-lim authored Feb 19, 2024
2 parents 531bcde + 1b93974 commit e3fc328
Show file tree
Hide file tree
Showing 12 changed files with 191 additions and 110 deletions.
2 changes: 1 addition & 1 deletion app/(route)/_components/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from "react";

const Footer = () => {
return (
<footer className="mb-72 w-full bg-gray-50 pc:mb-0 pc:py-32">
<footer className="mb-72 w-full bg-white-black pc:mb-0 pc:py-32">
<p className="p-20 text-12 font-500 leading-8 text-gray-500 pc:mx-auto pc:w-[104rem] pc:p-0">
Contact : mail, sns
<br />
Expand Down
39 changes: 22 additions & 17 deletions app/(route)/_components/carousel/Carousel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { Res_Get_Type } from "@/types/getResType";
import PrevButtonIcon from "@/public/icon/arrow-left_xl.svg";
import NextButtonIcon from "@/public/icon/arrow-right_xl.svg";

const SCROLLX = 20.8;

interface Props {
cards: Res_Get_Type["eventList"] | undefined;
}
Expand All @@ -27,42 +29,45 @@ const Carousel = ({ cards }: Props) => {

const handlePrevClick = () => {
if (!isPc) return;
const maxCardsToMove = Math.min(5, slideIndex);
if (slideIndex <= 0) return;
setSlideIndex((prev) => prev - 1);
setSlideIndex((prev) => prev - maxCardsToMove);
setIsNextDisabled(false);
if (slideIndex - 1 === 0) {
if (slideIndex - maxCardsToMove === 0) {
setIsPrevDisabled(true);
}
};

const handleNextClick = () => {
if (!isPc) return;
if (slideIndex >= (cards?.length || 0) - 5) return;
setSlideIndex((prev) => prev + 1);
const maxCardsToMove = Math.min(5, (cards?.length || 0) - slideIndex - 5);
setSlideIndex((prev) => prev + maxCardsToMove);
setIsPrevDisabled(false);
if (slideIndex + 1 === (cards?.length || 0) - 5) {
if (slideIndex + maxCardsToMove === (cards?.length || 0) - 5) {
setIsNextDisabled(true);
}
};

useEffect(() => {
if (cards && cards.length <= 5) {
setIsNextDisabled(true);
} else {
setIsNextDisabled(false);
}
}, [cards]);

return (
<div className="flex flex-col gap-16 pc:gap-24">
<div className="pc:flex pc:w-[112rem]">
<div onClick={handlePrevClick} className={`relative top-76 hidden h-100 w-[5rem] cursor-pointer pc:block ${isPrevDisabled ? "pointer-events-none opacity-50" : ""}`}>
<PrevButtonIcon />
</div>
<div className="flex gap-16 overflow-auto px-20 pc:gap-20 pc:overflow-hidden pc:p-0 pc:transition-transform pc:duration-1000 pc:ease-in-out">
{isPc
? cards?.slice(slideIndex, slideIndex + 5).map((event) => (
<div key={event.id}>
<VerticalEventCard data={event} />
</div>
))
: cards?.map((event) => (
<div key={event.id}>
<VerticalEventCard data={event} />
</div>
))}
<div className="flex w-full gap-16 overflow-auto px-20 pc:gap-20 pc:overflow-hidden pc:p-0">
{cards?.map((event) => (
<div key={event.id} className="pc:transition-transform pc:duration-500 pc:ease-in-out" style={{ transform: `translateX(-${slideIndex * SCROLLX}rem)` }}>
<VerticalEventCard data={event} />
</div>
))}
</div>
<div
onClick={handleNextClick}
Expand Down
83 changes: 46 additions & 37 deletions app/(route)/_components/carousel/FavArtistEventsCarousel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,62 +5,79 @@ import { instance } from "app/_api/api";
import Image from "next/image";
import Link from "next/link";
import { useRouter } from "next/navigation";
import { useState } from "react";
import { useEffect, useState } from "react";
import { useSession } from "@/store/session/cookies";
import { Res_Get_Type } from "@/types/getResType";
import Carousel from "./Carousel";

const FavArtistEventsCarousel = () => {
const [status, setStatus] = useState(false);
const session = useSession();

const [isSignin, setIsSignin] = useState(false);

const {
data: favArtistEvent,
isSuccess,
isLoading,
} = useQuery<Res_Get_Type["eventList"]>({
queryKey: ["event", "favoriteArtist"],
queryKey: ["artistNewEvent"],
queryFn: async () => {
return instance.get("/event/new");
if (!session) {
return;
}
return instance.get(`/event/new/${session.user.userId}/artist`, {
userId: session.user.userId,
});
},
});

// 데이터 길이를 기반으로 좋아요한 이벤트의 수 확인
// 추후 좋아요한 아티스트의 유무로 수정 예정
const hasFavoriteEvents = !!favArtistEvent?.length;

const renderContent = () => {
if (!status) {
return <NoFavCard buttonName="로그인 하기" href={"/signin"} />;
}

if (!hasFavoriteEvents) {
return <NoFavCard buttonName="아티스트 둘러보기" href={"/setting/artist"} />;
}

return (
<>
{isLoading && <div>로딩중</div>}
{isSuccess && <Carousel cards={favArtistEvent} />}
</>
);
};
useEffect(() => {
if (session?.isAuth) setIsSignin(true);
}, []);

return (
<div className="flex flex-col gap-16 pc:gap-24">
<div className="flex items-center justify-between self-stretch px-20 pc:px-48">
{status && (
{isSignin && (
<>
<h2 className="text-20 font-700 text-gray-900">내 아티스트의 새 행사</h2>
<Link href="/my-artist-event" className="text-12 font-600 text-blue">
<Link href="/my-artist-event?sort=최신순" className="text-12 font-600 text-blue">
전체보기
</Link>
</>
)}
</div>
{renderContent()}
<RenderContent status={isSignin} hasFavoriteEvents={!!favArtistEvent} isLoading={isLoading} isSuccess={isSuccess} favArtistEvent={favArtistEvent} />
</div>
);
};

interface RenderContentProps {
status?: boolean;
hasFavoriteEvents: boolean;
isLoading: boolean;
isSuccess: boolean;
favArtistEvent?: Res_Get_Type["eventList"];
}

const RenderContent = ({ status, hasFavoriteEvents, isLoading, isSuccess, favArtistEvent }: RenderContentProps) => {
if (!status) {
return <NoFavCard buttonName="로그인 하기" href={"/signin"} />;
}

return (
<>
{isLoading && <div>로딩중</div>}
{isSuccess && (
<>
{!hasFavoriteEvents && <NoFavCard buttonName="아티스트 둘러보기" href={"/setting/favorite"} />}
{hasFavoriteEvents && <Carousel cards={favArtistEvent} />}
</>
)}
</>
);
};

interface NoFavCardProps {
href: string;
buttonName: string;
Expand All @@ -72,17 +89,9 @@ export const NoFavCard = ({ href, buttonName }: NoFavCardProps) => {
return (
<div className="w-full px-20 pc:px-40">
<div className="flex-center relative h-160 overflow-hidden rounded-lg border border-main-pink-50 pc:h-232">
<Image
src="/image/hero.png"
fill
sizes="100%"
// style={{
// objectFit: "cover",
// }}
alt="배너이미지"
/>
<Image src="/image/hero.png" fill sizes="100%" className="object-cover" alt="배너이미지" />
<div className="flex-center absolute top-96 w-full flex-col gap-16 pc:top-152">
<div onClick={() => router.push(href)} className="pc:text-18 h-32 cursor-pointer rounded-full bg-gray-900 px-16 text-14 font-600 leading-loose text-white-white pc:h-40">
<div onClick={() => router.push(href)} className="h-32 cursor-pointer rounded-full bg-gray-900 px-16 text-14 font-600 leading-loose text-white-white pc:h-40 pc:text-18">
{buttonName}
</div>
</div>
Expand Down
82 changes: 74 additions & 8 deletions app/(route)/my-artist-event/_components/MyArtistEvent.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,80 @@
"use client";

import SortButton from "@/(route)/(bottom-nav)/search/_components/SortButton";
import { useInfiniteQuery } from "@tanstack/react-query";
import { usePathname, useRouter } from "next/navigation";
import { useEffect, useState } from "react";
import HorizontalEventCard from "@/components/card/HorizontalEventCard";
import { instance } from "@/api/api";
import useInfiniteScroll from "@/hooks/useInfiniteScroll";
import { useSession } from "@/store/session/cookies";
import { Res_Get_Type } from "@/types/getResType";
import SortIcon from "@/public/icon/sort.svg";

const SIZE = 20;

const SORT = ["최신순", "인기순"] as const;

const MyArtistEvent = () => {
// 좋아요 한 아티스트의 새 행사 로직은 추후 구현
const session = useSession();

const [sort, setSort] = useState<(typeof SORT)[number]>(SORT[0]);

const getArtistEvents = async ({ pageParam = 1 }) => {
if (!session) {
return;
}

const data: Res_Get_Type["artistEvent"] = await instance.get(`/event/${session.user.userId}/artist`, {
sort,
size: SIZE,
page: pageParam,
userId: session.user.userId,
});
return data;
};

const {
data: artistEvents,
fetchNextPage,
refetch,
} = useInfiniteQuery({
initialPageParam: 1,
queryKey: ["artistEvent"],
queryFn: getArtistEvents,
getNextPageParam: (lastPage) => lastPage && (lastPage.page * SIZE < lastPage.totalCount ? lastPage.page + 1 : null),
});

const containerRef = useInfiniteScroll({
handleScroll: fetchNextPage,
deps: [artistEvents],
});

const pathname = usePathname();
const router = useRouter();

useEffect(() => {
refetch();
router.push(`${pathname}?sort=${sort}`);
}, [sort]);

return (
<>
{/* {MOCK_EVENTS.map((event, index) => (
<div key={index}>
<HorizontalEventCard data={event} />
</div>
))} */}
</>
<div className="">
<h2 className="mb-24 hidden text-20 font-600 text-gray-900 pc:block">내 아티스트의 행사</h2>
<div className="flex items-center gap-8">
<SortIcon />
<SortButton onClick={() => setSort("최신순")} selected={sort === "최신순"}>
최신순
</SortButton>
<SortButton onClick={() => setSort("인기순")} selected={sort === "인기순"}>
인기순
</SortButton>
</div>
<div className="flex flex-wrap items-center gap-x-24">
{artistEvents?.pages.map((page) => page?.eventList.map((event) => <HorizontalEventCard key={event.id} data={event} />))}
<div ref={containerRef} className="h-16 w-full" />
</div>
</div>
);
};

Expand Down
2 changes: 1 addition & 1 deletion app/(route)/my-artist-event/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const MyArtistEventPage = () => {
return (
<DottedLayout size="wide">
<MobileHeader />
<div className="flex flex-col px-20 pb-88 pt-16">
<div className="px-20 pb-88 pt-16 pc:p-0 pc:pt-56">
<MyArtistEvent />
</div>
</DottedLayout>
Expand Down
43 changes: 25 additions & 18 deletions app/_api/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,10 @@ type GetEndPoint =
| "/group"
| "/artist"
| "/users/nickname"
| `/event/update/application/${string}`;
| `/event/update/application/${string}`
| `/event/${string}/artist`
| "/event/popularity"
| "/event/new";
type PostEndPoint =
| "/event"
| "/event/like"
Expand Down Expand Up @@ -170,23 +173,27 @@ type GetQueryType<T> = T extends "/event"
? Req_Query_Type["유저좋아요"]
: T extends `/event/update/application/${string}`
? Req_Query_Type["수정상세"]
: T extends `/event/${string}`
? Req_Query_Type["행사상세"]
: T extends "/artist/group"
? Req_Query_Type["아티스트"]
: T extends `/artist/${string}`
? Req_Query_Type["멤버"]
: T extends "/group/solo"
? Req_Query_Type["그룹솔로"]
: T extends `/reviews/user/${string}`
? Req_Query_Type["유저리뷰"]
: T extends `/reviews/${string}`
? Req_Query_Type["리뷰"]
: T extends "/group"
? Req_Query_Type["그룹조회"]
: T extends "/artist"
? Req_Query_Type["멤버조회"]
: unknown;
: T extends `/event/new/${string}/artist`
? Req_Query_Type["아티스트새행사"]
: T extends `/event/${string}/artist`
? Req_Query_Type["아티스트행사"]
: T extends `/event/${string}`
? Req_Query_Type["행사상세"]
: T extends "/artist/group"
? Req_Query_Type["아티스트"]
: T extends `/artist/${string}`
? Req_Query_Type["멤버"]
: T extends "/group/solo"
? Req_Query_Type["그룹솔로"]
: T extends `/reviews/user/${string}`
? Req_Query_Type["유저리뷰"]
: T extends `/reviews/${string}`
? Req_Query_Type["리뷰"]
: T extends "/group"
? Req_Query_Type["그룹조회"]
: T extends "/artist"
? Req_Query_Type["멤버조회"]
: unknown;
// 사용하실 때 직접 추가 부탁드립니다!
type PutBodyType<T> = T extends `/event/${string}`
? Req_Post_Type["event"]
Expand Down
2 changes: 1 addition & 1 deletion app/_components/BottomNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ const BottomNav = () => {
}, [session]);

return (
<nav className="fixed bottom-0 left-0 z-nav flex h-72 w-full items-center justify-evenly gap-28 border-t border-gray-50 bg-white-black py-8 shadow-top tablet:hidden">
<nav className="fixed bottom-0 left-0 z-nav flex h-72 w-full items-center justify-evenly gap-28 border-t border-gray-50 bg-white-black py-8 shadow-top pc:hidden">
{navButtons.map((item, index) => (
<NavButton key={index} href={item.href} icon={item.icon} label={item.label} isActive={pathname === item.href} />
))}
Expand Down
8 changes: 8 additions & 0 deletions app/_types/getResType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@ type Res_Get_Artist_Group = ArtistAndGroupListType;

type Res_Get_Edit_Application = EditApplicationType[];

type Res_Get_Artist_Event = {
eventList: EventCardType[];
page: number;
size: number;
totalCount: number;
};

export type Res_Get_Type = {
event: Res_Get_Event;
eventList: Res_Get_Event_List;
Expand All @@ -30,4 +37,5 @@ export type Res_Get_Type = {
eventReviews: Res_Get_EventReviews;
artistGroup: Res_Get_Artist_Group;
editApplication: Res_Get_Edit_Application;
artistEvent: Res_Get_Artist_Event;
};
Loading

0 comments on commit e3fc328

Please sign in to comment.