diff --git a/assets/images/home/blankimg.jpg b/assets/images/home/blankimg.jpg new file mode 100644 index 00000000..c532f617 Binary files /dev/null and b/assets/images/home/blankimg.jpg differ diff --git a/assets/images/home/ic_search.svg b/assets/images/home/ic_search.svg new file mode 100644 index 00000000..52241e6d --- /dev/null +++ b/assets/images/home/ic_search.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/logo/img_badge.svg b/assets/images/logo/img_badge.svg new file mode 100644 index 00000000..8470f48f --- /dev/null +++ b/assets/images/logo/img_badge.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/components/AllItemsSction.tsx b/components/AllItemsSction.tsx index a7616918..ad09d53d 100644 --- a/components/AllItemsSction.tsx +++ b/components/AllItemsSction.tsx @@ -38,7 +38,6 @@ interface AllItemsResponse { } function AllItem({ item }: { item: AllItemProps }) { - return (
@@ -56,6 +55,8 @@ function AllItem({ item }: { item: AllItemProps }) { ); } +const option = {"recent" : "최신순", "favorite" : "좋아요순"}; + function AllItemsSection() { const [alltItemsList, setAllItemsList] = useState([]); const [itemCount, setItemCount] = useState(getWidth()); @@ -63,7 +64,6 @@ function AllItemsSection() { const [poninter, setPoninter] = useState(1); const [title, setTitle] = useState("전체 상품"); const [pageSize, setPageSize] = useState(0); - const option = {"recent" : "최신순", "favorite" : "좋아요순"}; const AllItemsLoad = async (ItemCount: number, Order: string) => { const response: AllItemsResponse = await CallItemSearch(poninter, ItemCount, Order); setAllItemsList(response.list); diff --git a/components/BestItemsSection.tsx b/components/BestItemsSection.tsx index 8151610c..b7ffcff7 100644 --- a/components/BestItemsSection.tsx +++ b/components/BestItemsSection.tsx @@ -1,7 +1,7 @@ import { useEffect, useState } from "react"; import favicon from "@/assets/images/logo/favoriteIcon.svg"; import { CallItemSearch } from "@/pages/api/CallAPI"; -import style from "@/assets/BestItemsSection.module.css"; +import style from "@/styles/BestItemsSection.module.css"; import Link from "next/link"; import Image from "next/image"; diff --git a/components/Bestarticles.tsx b/components/Bestarticles.tsx index c3893ba0..6aa3eca5 100644 --- a/components/Bestarticles.tsx +++ b/components/Bestarticles.tsx @@ -1,36 +1,67 @@ import style from "@/styles/BestArticles.module.scss"; +import Image from "next/image"; +import BestImage from "@/assets/images/logo/img_badge.svg"; +import BlackImg from "@/assets/images/home/blankimg.jpg"; +import favoriteIcon from "@/assets/images/logo/favoriteIcon.svg"; +import DateFomet from "@/utils/DateFormet"; interface ArticlesProps { + id: number; + title: string; + content: string; + image: string | null; + likeCount: number; + createdAt: string; + updatedAt: string; + writer: { id: number; - title: string; - content: string; - image: File | null; - likeCount: number; - createAt: Date; - updateAt: Date; - writer: { - id: number; - nickname: string; - }; - } - + nickname: string; + }; +} -function BestArticles(articlesList: ArticlesProps[]) { +function Article({ item }: {item : ArticlesProps} ) { return ( -
-

베스트 게시글

-
-
-
-

게시글

- +
+
+

{item.title}

+ {item.image ? ( +
+ 게시글 사진 +
+ ) : (
- + 빈 이미지
-
+ )} +
+
- +

{item.writer.nickname}

+ 하트아이콘 +

{item.likeCount}

+

{DateFomet(item.updatedAt)}

+
+
+ ); +} + + +function BestArticles({ datalist }: { datalist: ArticlesProps[] }) { + return ( +
+

베스트 게시글

+
+ {datalist.map((item) => ( +
+ 베스트 아이콘 +
+
+ ))}
); diff --git a/components/Recentarticles.tsx b/components/Recentarticles.tsx deleted file mode 100644 index a4087adb..00000000 --- a/components/Recentarticles.tsx +++ /dev/null @@ -1,10 +0,0 @@ - -function Recentarticles() { - return ( -
- -
- ) -} - -export default Recentarticles; \ No newline at end of file diff --git a/components/Recentarticles/Recentarticles.module.scss b/components/Recentarticles/Recentarticles.module.scss new file mode 100644 index 00000000..4f5037fd --- /dev/null +++ b/components/Recentarticles/Recentarticles.module.scss @@ -0,0 +1,62 @@ +.recentArticlesLayer { + margin: 0 auto; + background-color: white; + .dataLayer { + background-color: #FCFCFC; + margin-bottom: 24px; + .articleData { + .articleDescription { + display: flex; + gap: 8px; + justify-content: space-between; + margin-bottom: 18px; + .articleTitle { + font-size: 20px; + font-weight: 600; + line-height: 32px; + color: #1f2937; + margin-right: 8px; + } + .articleImg { + width: 72px; + height: 72px; + border-radius: 6px; + background-color: white; + border: solid 1px var(--cool-Gray200); + position: relative; + } + .blankImage { + width: 72px; + height: 72px; + background-color: black; + } + } + .articleInfo { + display: flex; + justify-content: space-between; + + .userIcon { + margin-right: 8px; + } + + p { + font-size: 14px; + font-weight: 400; + line-height: 24px; + color: #4b5563; + } + div { + display: flex; + align-items: center; + p { + margin-right: 8px; + } + img { + margin-right: 4px; + } + } + } + } + + } +} \ No newline at end of file diff --git a/components/Recentarticles/Recentarticles.tsx b/components/Recentarticles/Recentarticles.tsx new file mode 100644 index 00000000..dfb4e7c8 --- /dev/null +++ b/components/Recentarticles/Recentarticles.tsx @@ -0,0 +1,68 @@ +import style from "./Recentarticles.module.scss" +import favoriteIcon from "@/assets/images/logo/favoriteIcon.svg"; +import BlackImg from "@/assets/images/home/blankimg.jpg"; +import DateFomet from "@/utils/DateFormet"; +import Image from "next/image"; +import MaskIcon from "@/assets/images/home/maskicon.png" + +interface ArticlesProps { + id: number; + title: string; + content: string; + image: string | null; + likeCount: number; + createdAt: string; + updatedAt: string; + writer: { + id: number; + nickname: string; + }; +} + +function Article({ item }: {item : ArticlesProps }) { + return ( +
+
+

{item.title}

+ {item.image ? ( +
+ 게시글 사진 +
+ ) : ( +
+ 빈 이미지 +
+ )} +
+
+
+ 유저아이콘 +

{item.writer.nickname}

+

{DateFomet(item.updatedAt)}

+
+
+ 하트아이콘 +

{item.likeCount}

+
+
+
+ ); +} + +function Recentarticles({ datalist } : {datalist: ArticlesProps[]}) { + return ( +
+ {datalist.map((item) => ( +
+
+
+ ))} +
+ ) +} + +export default Recentarticles; \ No newline at end of file diff --git a/hook/useDevice.tsx b/hook/useDevice.tsx new file mode 100644 index 00000000..5ea13260 --- /dev/null +++ b/hook/useDevice.tsx @@ -0,0 +1,28 @@ +import { useEffect, useState } from "react"; +import { DeviceType, getDevice } from "@/utils/widthUtil"; + +const useDevice = () => { + const [mode, setMode] = useState("desktop"); + + useEffect(() => { + const ReCount = () => { + const device = getDevice(); + setMode(device); + }; + + window.addEventListener("resize", ReCount); + + // 초기화 + ReCount(); + + return () => { + window.removeEventListener("resize", ReCount); + }; + }, []); + + return { + mode, + }; +}; + +export default useDevice; diff --git a/pages/boards.tsx b/pages/boards.tsx index 4f30b667..4f2b5225 100644 --- a/pages/boards.tsx +++ b/pages/boards.tsx @@ -1,17 +1,22 @@ import { CallArticles } from "./api/CallAPI"; +import { ChangeEvent, useMemo } from "react"; import style from "@/styles/Boards.module.scss"; import BestArticles from "@/components/BestArticles"; -import Recentarticles from "@/components/Recentarticles"; +import Recentarticles from "@/components/Recentarticles/Recentarticles"; +import DropDownSort from "@/components/DropDownSort"; import { useEffect, useState } from "react"; +import Image from "next/image"; +import seachIcon from "@/assets/images/home/ic_search.svg"; +import useDevice from "@/hook/useDevice"; interface ArticlesProps { id: number; title: string; content: string; - image: File | null; + image: string | null; likeCount: number; - createAt: Date; - updateAt: Date; + createdAt: string; + updatedAt: string; writer: { id: number; nickname: string; @@ -20,33 +25,67 @@ interface ArticlesProps { interface ArticlesResopnse { list: ArticlesProps[]; + totalCount: number; } +const option = { "recent" : "최신순", "like" : "좋아요순"}; + function boards() { const [keyWord, setKeyWord] = useState(); const [order, setOrder] = useState("recent"); const [articlesList, setArticlesList] = useState([]); const [bestArticlesList, setBestArticlesList] = useState([]); - const ArticlesLoad = async (keyword: string | undefined, order: string) => { + const ArticlesLoad = async (keyWord: string | undefined, order: string) => { const response: ArticlesResopnse = await CallArticles(keyWord, order, 20); setArticlesList(response.list); }; + + const KeyWordInput = (e: ChangeEvent) => { + setKeyWord(e.target.value); + } + const BestArticlesLoad = async () => { - const response: ArticlesResopnse = await CallArticles(undefined, "like", 3); + const response: ArticlesResopnse = await CallArticles(undefined, "like", bestCount); setBestArticlesList(response.list); - console.log(response.list); }; + const { mode } = useDevice(); + const bestCount = useMemo(() => { + + console.log(mode); + + switch (mode) { + case "desktop": + return 3 + case "tablet": + return 2 + case "mobile": + return 1 + } + }, [mode]) useEffect(() => { ArticlesLoad(keyWord, order); + }, [keyWord, order]); + + useEffect(() => { BestArticlesLoad(); - }, []); + }, [bestCount]); return ( -
- {/* */} -

aaa

- +
+
+ +
+

게시글

+ +
+
+ 검색 아이콘 + + +
+ +
); } diff --git a/pages/items/[productid].tsx b/pages/items/[productid].tsx index 94039968..a9950a8b 100644 --- a/pages/items/[productid].tsx +++ b/pages/items/[productid].tsx @@ -1,14 +1,14 @@ import { useEffect, useState } from "react"; -import heartIcon from "@/public/images/logo/favoriteIcon.svg"; +import heartIcon from "@/assets/images/logo/favoriteIcon.svg"; import { CallItemDetail } from "@/pages/api/CallAPI"; import { CallItemComment } from "@/pages/api/CallAPI"; import Link from "next/link"; import { useRouter } from "next/router"; import styled from "styled-components"; -import BackIcon from "@/public/images/home/ic_back.svg"; -import More from "@/public/images/home/ic_kebab.svg"; -import UserIcon from "@/public/images/home/maskicon.png" -import NotComment from "@/public/images/home/not_comment.svg"; +import BackIcon from "@/assets/images/home/ic_back.svg"; +import More from "/assets/images/home/ic_kebab.svg"; +import UserIcon from "@/assets/images/home/maskicon.png" +import NotComment from "/assets/images/home/not_comment.svg"; import Image from "next/image"; const ItemDetailLayer = styled.div` diff --git a/styles/BestArticles.module.scss b/styles/BestArticles.module.scss index e69de29b..60e86ab9 100644 --- a/styles/BestArticles.module.scss +++ b/styles/BestArticles.module.scss @@ -0,0 +1,83 @@ +.bestArticleLayer { + margin: 0 auto; + margin-bottom: 40px; + + .bestArtitlceTitle { + margin-bottom: 24px; + font-size: 20px; + font-weight: 700; + line-height: 23.87px; + color: var(--cool-Gray900); + } + .bestArticleList { + display: flex; + justify-content: center; + gap: 24px; + + .bestArticle { + display: flex; + width: 384px; + flex-direction: column; + background-color: var(--cool-Gray50); + border-radius: 8px; + padding: 0px 24px 8px 24px; + .bestIcon { + margin-bottom: 16px; + } + .articleData { + .articleDescription { + display: flex; + gap: 8px; + justify-content: space-between; + margin-bottom: 18px; + .articleTitle { + font-size: 20px; + font-weight: 600; + line-height: 32px; + color: #1f2937; + margin-right: 8px; + } + .articleImg { + width: 72px; + height: 72px; + border-radius: 6px; + background-color: white; + border: solid 1px var(--cool-Gray200); + position: relative; + } + .blankImage { + width: 72px; + height: 72px; + background-color: black; + } + } + .articleInfo { + display: flex; + justify-content: space-between; + + .userIcon { + margin-right: 8px; + } + + p { + font-size: 14px; + font-weight: 400; + line-height: 24px; + color: #4b5563; + } + div { + display: flex; + align-items: center; + p { + margin-right: 8px; + } + img { + margin-right: 4px; + } + } + } + } + + } + } +} \ No newline at end of file diff --git a/styles/Boards.module.scss b/styles/Boards.module.scss index f1f145d2..afdcb909 100644 --- a/styles/Boards.module.scss +++ b/styles/Boards.module.scss @@ -1,6 +1,49 @@ -.articleslayer { +.container { margin: 24px auto; - p { - font-size: 50px; + display: flex; + flex-direction: column; + padding: 0 24px ; + + .articleLayer { + margin: 0 auto; + @media (768px < width < 1280px ) { + max-width: 696px; + } + .menuLayer { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 24px; + position: relative; + p { + font-size: 20px; + font-weight: 700; + line-height: 32px; + color: #1f2937; + } + + .seachIcon { + position: absolute; + left: 20px; + } + + input { + background-color: #f3f4f6; + width: 100%; + padding: 9px 44px; + margin-right: 16px; + border-radius: 12px; + } + + button { + border-radius: 8px; + background-color: var(--brand-blue); + padding: 12px 23px; + color: white; + font-size: 16px; + font-weight: 600; + line-height: 19.09px; + } + } } -} \ No newline at end of file +} diff --git a/styles/DropDownSort.module.css b/styles/DropDownSort.module.css index 35c78930..4f4f0430 100644 --- a/styles/DropDownSort.module.css +++ b/styles/DropDownSort.module.css @@ -5,6 +5,7 @@ padding: 12px 20px; border: 1px var(--cool-Gray200) solid; color: var(--cool-Gray800); + position: relative; } /* 모바일버전 */ @@ -12,7 +13,7 @@ .SortMenu { width: 42px; height: 42px; - background-image: url("../public/images/home/sorticon.svg"); + background-image: url("../assets/images/home/sorticon.svg"); background-position: center; background-size: cover; -webkit-appearance: none; /* 크롬, 사파리, 오페라 */ diff --git a/styles/globals.css b/styles/globals.css index f19aa9eb..f9a19933 100644 --- a/styles/globals.css +++ b/styles/globals.css @@ -7,6 +7,7 @@ --cool-Gray200 : #E5E7EB; --cool-Gray500 : #6b7280; --cool-Gray50 : #f9fafb; + --cool-Gray900 : #111827; } /* 기본 css 초기화 */ diff --git a/utils/DateFormet.tsx b/utils/DateFormet.tsx new file mode 100644 index 00000000..3ff278a0 --- /dev/null +++ b/utils/DateFormet.tsx @@ -0,0 +1,16 @@ +function DateFomet(strdate:string) { + const date = new Date(strdate); + + const year = date.getUTCFullYear(); + const month = String(date.getUTCMonth() + 1).padStart(2, '0'); + const day = String(date.getUTCDate()).padStart(2, '0'); + const hours = String(date.getUTCHours()).padStart(2, '0'); + const minutes = String(date.getUTCMinutes()).padStart(2, '0'); + const seconds = String(date.getUTCSeconds()).padStart(2, '0'); + const formattedDate = `${year}. ${month}. ${day}`; + const formattedTime = `${hours}:${minutes}:${seconds}`; + + return `${formattedDate}`; + } + + export default DateFomet; \ No newline at end of file diff --git a/utils/widthUtil.ts b/utils/widthUtil.ts new file mode 100644 index 00000000..bae1a57b --- /dev/null +++ b/utils/widthUtil.ts @@ -0,0 +1,12 @@ +export type DeviceType = "mobile" | "tablet" | "desktop"; + +export function getDevice(): DeviceType { + let width = window.innerWidth; + if (width < 768) { + return "mobile"; + } else if (width < 1280) { + return "tablet"; + } else { + return "desktop"; + } +}