Skip to content
49 changes: 27 additions & 22 deletions src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import LandingMid from "@component/components/landing/carousel/LandingMid";
import ProjectList from "@component/components/landing/project/ProjectList";
import { Suspense, useEffect, useState } from "react";
import SignUpModal from "@component/components/signup/SignUpModal";
import Image from "next/image";
import useWindowSize from "@component/hooks/useWindowSize";

export default function Home() {
const [isOpen, setIsOpen] = useState<boolean>(false);
Expand All @@ -17,33 +17,38 @@ export default function Home() {
}
}, []);

const { width } = useWindowSize();

return (
// ์ „์ฒด 1440px
<main className="mx-auto w-full flex flex-col items-center">
{/* ๋žœ๋”ฉ ๋ฌธ๊ตฌ */}
<>
<section
className="w-full h-[620px] bg-purple-main4 flex justify-center"
style={{
backgroundImage: "url('/assets/main_background.png')",
backgroundSize: "cover",
}}
className={`absolute scale-75 ${width ?? 0 >= 1460 ? "fixed left-[20%] transform-1/2-1/2" : "flex justify-center items-center min-w-[1460px] max-[1920px]"}`}
>
<section className="w-[1080px] scale-75 mx-auto">
<LandingTop />
</section>
<LandingTop />
</section>
<main className="mx-auto w-full flex flex-col items-center mt-[70px]">
{/* ๋žœ๋”ฉ ๋ฌธ๊ตฌ */}
<section
className="w-full max-w-[1470px] h-[620px] flex justify-center items-center"
style={{
backgroundImage: "url('/assets/main_background.png')",
backgroundSize: "cover",
}}
></section>

{/* ์ปจํ…Œ์ด๋„ˆ ๋„ˆ๋น„ */}
<section className="max-w-[1080px] w-full mt-[100px] flex flex-col gap-[100px] mb-[100px]">
{/* ์บ๋Ÿฌ์…€ */}
<LandingMid />
<Suspense>
{/* ํ”„๋กœ์ ํŠธ */}
<ProjectList />
</Suspense>
</section>
{/* ์ปจํ…Œ์ด๋„ˆ ๋„ˆ๋น„ */}
<section className="max-w-[1080px] w-full mt-[100px] flex flex-col gap-[100px] mb-[100px]">
{/* ์บ๋Ÿฌ์…€ */}
<LandingMid />
<Suspense>
{/* ํ”„๋กœ์ ํŠธ */}
<ProjectList />
</Suspense>
</section>

{isOpen && <SignUpModal isOpen={isOpen} setIsOpen={setIsOpen} />}
</main>
{isOpen && <SignUpModal isOpen={isOpen} setIsOpen={setIsOpen} />}
</main>
</>
);
}
36 changes: 20 additions & 16 deletions src/components/landing/carousel/Carousel.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
"use client";
import RecommendItem from "./RecommendItem";
import { useEffect, useState } from "react";
import { TagProps } from "@component/components/common-components/tag";
import { useMemo } from "react";
import Slider from "react-slick";
import "slick-carousel/slick/slick.css";
import "slick-carousel/slick/slick-theme.css";
import { useGetProjectRecommend } from "@component/hooks/useProject";
import { RecommendDataType } from "./Carousel.types";

// ์บ๋Ÿฌ์…€ ํ™”์‚ดํ‘œ
import ArrowBackIosNewRoundedIcon from "@mui/icons-material/ArrowBackIosNewRounded";
Expand Down Expand Up @@ -38,40 +38,44 @@ const settings = {
slidesToShow: 3, // ํ™”๋ฉด์— ํ•œ ๋ฒˆ์— ํ‘œ์‹œํ•  ์Šฌ๋ผ์ด๋“œ ๊ฐœ์ˆ˜ ์„ค์ •
slidesToScroll: 3, // ๋‹ค์Œ ๋ณด์—ฌ ์ค„ ์Šฌ๋ผ์ด๋“œ์˜ ๊ฐœ์ˆ˜ ์„ค์ •
speed: 2000, // ํ™”๋ฉด์„ ๋„˜๊ธธ ๋•Œ ์†๋„
autoplay: false, // TODO: ์ž๋™ ๋„˜๊น€ ๋…ผ์˜
autoplay: false,
autoplaySpeed: 5000, // ๊ฐ„๊ฒฉ
nextArrow: <NextArrow />,
prevArrow: <PrevArrow />,
};

const Carousel = () => {
const { data, error, isLoading } = useGetProjectRecommend();
const [recommendData, setRecommendData] = useState<any>();

useEffect(() => {
if (data) {
setRecommendData(data.data.data)
}
const recommendData: RecommendDataType[] = useMemo(() => {
return data?.data.data ?? [];
}, [data]);

if (error) {
console.log(error);
if (isLoading || error) {
return (
<Slider {...settings} className="mt-[32.5px]">
{[...Array(3)].map((_, index) => (
<div>
<div className="w-[344px] h-[340px] rounded-[10px] border border-[1.5px] border-purple-main1 bg-purple-main5 flex justify-center items-center"></div>
</div>
))}
</Slider>
);
}
return (
<>
<Slider {...settings} className="mt-[32.5px]">
{recommendData?.map((item: any) => (
{recommendData?.map((item: RecommendDataType) => (
<RecommendItem
key={item.projectId}
projectId={item.projectId}
fields={item.field}
field={item.field}
progress={item.progress}
title={item.title}
content={item.summary}
profileImg={item.profileImageUrl}
nickname={item.createdBy}
summary={item.summary}
profileImageUrl={item.profileImageUrl}
createdBy={item.createdBy}
createdAt={item.createdAt}
isLoading={isLoading}
/>
))}
</Slider>
Expand Down
13 changes: 13 additions & 0 deletions src/components/landing/carousel/Carousel.types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { TagProps } from "@component/components/common-components/tag";

export type RecommendDataType = {
createdAt: string;
createdBy: string;
field: TagProps["type"];
profileImageUrl: string;
progress: TagProps["status"];
projectId: number;
summary: string;
title: string;
}

2 changes: 1 addition & 1 deletion src/components/landing/carousel/LandingTop.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ const LandingTop = () => {
<div className="text-title mt-[32px] text-white">
์—ฌ๋Ÿฌ ๋ถ„์•ผ์˜ ์„œ๋น„์Šค ์œ ์ €๋กœ๋ถ€ํ„ฐ ์œ ์˜๋ฏธํ•œ ํ”ผ๋“œ๋ฐฑ์„ ๋ฐ›์„ ์ˆ˜ ์žˆ์–ด์š”.
</div>
<Button size="lg" className="mt-[100px] min-w-[246px]" onClick={onClickProject}>
<Button size="lg" className="mt-[100px] min-w-[246px] text-h1" onClick={onClickProject}>
ํ”„๋กœ์ ํŠธ ๋“ฑ๋กํ•˜๊ธฐ
</Button>
<Toaster />
Expand Down
81 changes: 43 additions & 38 deletions src/components/landing/carousel/RecommendItem.tsx
Original file line number Diff line number Diff line change
@@ -1,45 +1,50 @@
import Image from "next/image";
import Tag from "@component/components/common-components/tag/Tag";
import { useRouter } from "next/navigation";
import { RecommendDataType } from "./Carousel.types";

const RecommendItem = ({
projectId,
fields,
progress,
title,
content,
profileImg,
nickname,
createdAt,
isLoading
}: any) => {
const router = useRouter();
return (
<>
{isLoading ? (
<div className="w-[344px] h-[340px] rounded-[10px] border border-[1.5px] border-purple-main1 bg-purple-main5 flex justify-center items-center cursor-pointer">
</div>
) : (
<div
className="w-[344px] h-[340px] rounded-[10px] border border-[1.5px] border-purple-main1 bg-purple-main5 flex justify-center items-center cursor-pointer"
onClick={() => {
router.push(`/project/${projectId}`)
}}
>
<div className="w-[261px] h-[296.93px] relative">
<Tag type={fields} status={progress} />
<div className="text-title mt-[12px] mb-[24px]">{title}</div>
<div className="text-body1 text-gray-60 font-medium">{content}</div>
<div className="absolute bottom-0 flex items-center">
<Image src={profileImg} alt="์ž„์‹œ ํ”„๋กœํ•„ ์ด๋ฏธ์ง€" width={20} height={20} className="w-[20px] h-[20px] rounded-full me-[10px]" />
<div className="text-body1 text-gray-60 me-[24px] font-medium">{nickname}</div>
<div className="text-body1 text-gray-60 font-medium">{createdAt}</div>
</div>
</div>
</div>
)}
</>
);
}
projectId,
field,
progress,
title,
summary,
profileImageUrl,
createdBy,
createdAt,
}: RecommendDataType) => {
const router = useRouter();
return (
<>
<div
className="w-[344px] h-[340px] rounded-[10px] border border-[1.5px] border-purple-main1 bg-purple-main5 flex justify-center items-center cursor-pointer"
onClick={() => {
router.push(`/project/${projectId}`);
}}
>
<div className="w-[261px] h-[296.93px] relative">
<Tag type={field} status={progress} />
<div className="text-title mt-[12px] mb-[24px]">{title}</div>
<div className="text-body1 text-gray-60 font-medium">{summary}</div>
<div className="absolute bottom-0 flex items-center">
<Image
src={profileImageUrl}
alt="์ž„์‹œ ํ”„๋กœํ•„ ์ด๋ฏธ์ง€"
width={20}
height={20}
className="w-[20px] h-[20px] rounded-full me-[10px]"
/>
<div className="text-body1 text-gray-60 me-[24px] font-medium">
{createdBy}
</div>
<div className="text-body1 text-gray-60 font-medium">
{createdAt}
</div>
</div>
</div>
</div>
</>
);
};

export default RecommendItem;
34 changes: 34 additions & 0 deletions src/hooks/useWindowSize.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { useState, useEffect } from "react";

interface Size {
width: number | undefined;
height: number | undefined;
}

// Hook
function useWindowSize(): Size {

const [windowSize, setWindowSize] = useState<Size>({
width: undefined,
height: undefined,
});
useEffect(() => {

function handleResize() {

setWindowSize({
width: window.innerWidth,
height: window.innerHeight,
});
}

window.addEventListener("resize", handleResize);

handleResize();

return () => window.removeEventListener("resize", handleResize);
}, []);
return windowSize;
}

export default useWindowSize;