-
-
게시글
-
+
+
+
{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)}
+
+
+
+
+ );
+}
+
+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";
+ }
+}