diff --git a/package-lock.json b/package-lock.json index ebf9055d..79f749fa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3123,8 +3123,7 @@ "node_modules/@ungap/structured-clone": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" }, "node_modules/@vitejs/plugin-react": { "version": "4.2.1", @@ -4313,7 +4312,6 @@ "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, "dependencies": { "ms": "2.1.2" }, @@ -8511,8 +8509,7 @@ "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/msw": { "version": "1.3.2", diff --git a/src/mocks/handlers.ts b/src/mocks/handlers.ts index 2414eb05..8ddd49c8 100644 --- a/src/mocks/handlers.ts +++ b/src/mocks/handlers.ts @@ -2,6 +2,7 @@ import { rest } from "msw" import { searchHandlers } from "@components/Search/mocks" +import allProjectHandlers from "@pages/HomePage/mocks" import { projectDetailHandlers } from "@pages/ProjectDetailPage/mocks" import { postEmailLogin } from "./auth/postEmailLogin.mock" @@ -29,6 +30,7 @@ export const handlers = [ }), ...projectDetailHandlers, ...searchHandlers, + ...allProjectHandlers, postEmailRefresh, postEmailLogin, ] diff --git a/src/pages/HomePage/HomePage.tsx b/src/pages/HomePage/HomePage.tsx index e6255eb1..53e93cfe 100644 --- a/src/pages/HomePage/HomePage.tsx +++ b/src/pages/HomePage/HomePage.tsx @@ -1,5 +1,125 @@ +import { ChangeEvent, useState } from "react" +import { Link } from "react-router-dom" + +import { + Box, + Button, + Center, + Checkbox, + Container, + Grid, + GridItem, + HStack, + Select, + Skeleton, + Spacer, + Stack, +} from "@chakra-ui/react" + +import ProjectCard from "@components/ProjectCard/ProjectCard" + +import Banner from "./components/Banner/Banner" +import useAllProjectQuery from "./hooks/queries/useAllProjectQuery" + +type SelectType = "default" | "likeCount" | "viewCount" + const HomePage = () => { - return
HomePage
+ const [isDeploy, setIsDeploy] = useState(false) + const [selectedOption, setSelectedOption] = useState("default") + + // 프로젝트 전체 목록 조회 + const { allProjectList, isAllProjectLoading } = useAllProjectQuery() + + const projectList = allProjectList?.projects.filter((project) => + isDeploy ? project.isDeploy : project, + ) + + const handleSelect = (e: ChangeEvent) => { + const value = e.target.value as SelectType + setSelectedOption(value) + } + return ( + <> + {/* 임시로 다섯개 잘라서 넣었습니다*/} + {isAllProjectLoading ? ( + + ) : ( + + )} + + + + + setIsDeploy(!isDeploy)}> + 출시 서비스만 보기 + + + + + {isAllProjectLoading ? ( + <> + + + + + + ) : ( + projectList?.map((project) => ( + + + + + + )) + )} + +
+ +
+
+ +
+ {/* 푸터 들어갈 자리 */} + + ) } export default HomePage diff --git a/src/pages/HomePage/components/Banner/Banner.style.tsx b/src/pages/HomePage/components/Banner/Banner.style.tsx new file mode 100644 index 00000000..15d8be68 --- /dev/null +++ b/src/pages/HomePage/components/Banner/Banner.style.tsx @@ -0,0 +1,26 @@ +import { Swiper } from "swiper/react" + +import styled from "styled-components" + +export const CustomSwiper = styled(Swiper)` + .swiper-button-prev, + .swiper-button-next { + opacity: 0; + border-radius: 10rem; + color: white; + + &:hover { + opacity: 0.8; + transition: 0.2s ease-out; + } + + &:after { + font-size: 2.2rem !important; + font-weight: 600 !important; + } + } + + .swiper-pagination-bullet { + background: ${({ theme }) => theme.yellow[100]} !important; + } +` diff --git a/src/pages/HomePage/components/Banner/Banner.tsx b/src/pages/HomePage/components/Banner/Banner.tsx new file mode 100644 index 00000000..6341f2d8 --- /dev/null +++ b/src/pages/HomePage/components/Banner/Banner.tsx @@ -0,0 +1,75 @@ +import { Link, useNavigate } from "react-router-dom" + +import { + HStack, + Heading, + Image, + Spacer, + Stack, + Text, + useTheme, +} from "@chakra-ui/react" +import { AllProject } from "api-models" +import "swiper/css" +import "swiper/css" +import "swiper/css/navigation" +import "swiper/css/pagination" +import { Autoplay, Navigation, Pagination } from "swiper/modules" +import { SwiperSlide } from "swiper/react" + +import { CustomSwiper } from "./Banner.style" + +interface bannerListProps { + bannerList: AllProject[] | undefined +} + +const Banner = ({ bannerList }: bannerListProps) => { + const navigate = useNavigate() + const theme = useTheme() + + return ( + + {bannerList?.map((project) => ( + + + projectImg navigate(`/project/${project.id}`)} + /> + + + + + {project.subName} + + {project.name} + + + + + ))} + + ) +} +export default Banner diff --git a/src/pages/HomePage/hooks/queries/useAllProjectQuery.ts b/src/pages/HomePage/hooks/queries/useAllProjectQuery.ts new file mode 100644 index 00000000..c14fab78 --- /dev/null +++ b/src/pages/HomePage/hooks/queries/useAllProjectQuery.ts @@ -0,0 +1,18 @@ +import { useQuery } from "@tanstack/react-query" + +import { getAllProjects } from "@/api/project/getAllProjects" + +const useAllProjectQuery = () => { + const { data, isLoading, refetch } = useQuery({ + queryKey: ["projects"], + queryFn: () => getAllProjects(), + }) + + return { + allProjectList: data, + isAllProjectLoading: isLoading, + refetchAllProject: refetch, + } +} + +export default useAllProjectQuery diff --git a/src/pages/HomePage/mocks/index.ts b/src/pages/HomePage/mocks/index.ts new file mode 100644 index 00000000..8c8b563e --- /dev/null +++ b/src/pages/HomePage/mocks/index.ts @@ -0,0 +1,13 @@ +import { rest } from "msw" + +import { ENDPOINTS } from "@constants/endPoints" + +import { mockData } from "./mockData" + +const allProjectHandlers = [ + rest.get(ENDPOINTS.GET_ALL_PROJECTS, (_, res, ctx) => { + return res(ctx.status(200), ctx.json(mockData)) + }), +] + +export default allProjectHandlers diff --git a/src/pages/HomePage/mocks/mockData.ts b/src/pages/HomePage/mocks/mockData.ts new file mode 100644 index 00000000..fe711a0e --- /dev/null +++ b/src/pages/HomePage/mocks/mockData.ts @@ -0,0 +1,155 @@ +export const mockData = { + projects: [ + { + id: 1, + name: "사이드픽👀", + subName: "요즘 사이드 플젝 뭐함? 사이드픽 👀", + thumbnailUrl: "https://picsum.photos/200", + viewCount: 20, + likeCount: 7, + isLiked: false, + isDeploy: false, + }, + { + id: 2, + name: "냠냠디저트", + subName: "냠냠디저트 맛집 공유 플랫폼", + thumbnailUrl: "https://picsum.photos/200", + viewCount: 95, + likeCount: 7, + isLiked: true, + isDeploy: true, + }, + { + id: 3, + name: "사이드픽👀", + subName: "요즘 사이드 플젝 뭐함? 사이드픽 👀", + thumbnailUrl: "https://picsum.photos/200", + viewCount: 20, + likeCount: 7, + isLiked: false, + isDeploy: false, + }, + { + id: 4, + name: "냠냠디저트", + subName: "냠냠디저트 맛집 공유 플랫폼", + thumbnailUrl: "https://picsum.photos/200", + viewCount: 95, + likeCount: 7, + isLiked: true, + isDeploy: true, + }, + { + id: 5, + name: "사이드픽👀", + subName: "요즘 사이드 플젝 뭐함? 사이드픽 👀", + thumbnailUrl: "https://picsum.photos/200", + viewCount: 20, + likeCount: 7, + isLiked: false, + isDeploy: false, + }, + { + id: 6, + name: "냠냠디저트", + subName: "냠냠디저트 맛집 공유 플랫폼", + thumbnailUrl: "https://picsum.photos/200", + viewCount: 95, + likeCount: 7, + isLiked: true, + isDeploy: true, + }, + { + id: 7, + name: "사이드픽👀", + subName: "요즘 사이드 플젝 뭐함? 사이드픽 👀", + thumbnailUrl: "https://picsum.photos/200", + viewCount: 20, + likeCount: 7, + isLiked: false, + isDeploy: false, + }, + { + id: 8, + name: "냠냠디저트", + subName: "냠냠디저트 맛집 공유 플랫폼", + thumbnailUrl: "https://picsum.photos/200", + viewCount: 95, + likeCount: 7, + isLiked: true, + isDeploy: true, + }, + { + id: 9, + name: "냠냠디저트", + subName: "냠냠디저트 맛집 공유 플랫폼", + thumbnailUrl: "https://picsum.photos/200", + viewCount: 95, + likeCount: 7, + isLiked: true, + isDeploy: true, + }, + { + id: 10, + name: "사이드픽👀", + subName: "요즘 사이드 플젝 뭐함? 사이드픽 👀", + thumbnailUrl: "https://picsum.photos/200", + viewCount: 20, + likeCount: 7, + isLiked: false, + isDeploy: false, + }, + { + id: 11, + name: "냠냠디저트", + subName: "냠냠디저트 맛집 공유 플랫폼", + thumbnailUrl: "https://picsum.photos/200", + viewCount: 95, + likeCount: 7, + isLiked: true, + isDeploy: true, + }, + { + id: 12, + name: "사이드픽👀", + subName: + "요즘 사이드 플젝 뭐함? 사이드픽 👀 하하하하하하하ㅏ하핳하하하하하하하하하", + thumbnailUrl: "https://picsum.photos/200", + viewCount: 100, + likeCount: 7, + isLiked: false, + isDeploy: false, + }, + { + id: 13, + name: "냠냠디저트", + subName: "냠냠디저트 맛집 공유 플랫폼", + thumbnailUrl: "https://picsum.photos/200", + viewCount: 95, + likeCount: 9, + isLiked: true, + isDeploy: true, + }, + { + id: 14, + name: "사이드픽👀", + subName: "요즘 사이드 플젝 뭐함? 사이드픽 👀", + thumbnailUrl: "https://picsum.photos/200", + viewCount: 20, + likeCount: 3, + isLiked: false, + isDeploy: false, + }, + { + id: 15, + name: "냠냠디저트", + subName: "냠냠디저트 맛집 공유 플랫폼", + thumbnailUrl: "https://picsum.photos/200", + viewCount: 95, + likeCount: 10, + isLiked: true, + isDeploy: true, + }, + ], +} diff --git a/src/types/domain/apiDomain.d.ts b/src/types/domain/apiDomain.d.ts index 04bdaa87..8917a1bd 100644 --- a/src/types/domain/apiDomain.d.ts +++ b/src/types/domain/apiDomain.d.ts @@ -56,6 +56,17 @@ declare module "api-models" { troubleShooting: string } + export type AllProject = { + id: number + name: string + subName: string + thumbnailUrl: string + viewCount: number + likeCount: number + isLiked: boolean + isDeploy: boolean + } + export type Description = { content: string imageUrls: string[] @@ -230,7 +241,7 @@ declare module "api-models" { } export type getAllProjectsResponseType = { - projects: Project[] + projects: AllProject[] } export type putProjectPayload = {