From 500ef334453a0f69aeee260884550ae9c39eff88 Mon Sep 17 00:00:00 2001 From: CHAE Date: Tue, 4 Jun 2024 14:53:13 +0900 Subject: [PATCH 01/13] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Refactor:=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=EB=A6=AC=EB=B7=B0=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env | 2 +- .gitignore | 3 +++ apis/api.ts | 2 +- apis/getArticles.ts | 11 ++++++----- hooks/useSetNumberOfItemsToShow.ts | 5 ++--- .../boards/BestPost/components/PostElement/index.tsx | 7 +++++-- 6 files changed, 18 insertions(+), 12 deletions(-) diff --git a/.env b/.env index fbea1b7f7..82504247e 100644 --- a/.env +++ b/.env @@ -1,3 +1,3 @@ -REACT_APP_API_KEY = https://panda-market-api.vercel.app/ +REACT_APP_API_URL = https://panda-market-api.vercel.app/ NEXT_PUBLIC_BASE_URL=https://panda-market-api.vercel.app/ \ No newline at end of file diff --git a/.gitignore b/.gitignore index 8f322f0d8..9472f45e3 100644 --- a/.gitignore +++ b/.gitignore @@ -33,3 +33,6 @@ yarn-error.log* # typescript *.tsbuildinfo next-env.d.ts + + +.env \ No newline at end of file diff --git a/apis/api.ts b/apis/api.ts index 497f36349..4586456d6 100644 --- a/apis/api.ts +++ b/apis/api.ts @@ -1,7 +1,7 @@ import axios from "axios"; const panda_market_backend_api = process.env.NEXT_PUBLIC_BASE_URL; -export const baseAxios = axios.create({ +export const axiosInstance = axios.create({ baseURL: panda_market_backend_api, timeout: 20000, }); diff --git a/apis/getArticles.ts b/apis/getArticles.ts index 31079cefd..322876edc 100644 --- a/apis/getArticles.ts +++ b/apis/getArticles.ts @@ -1,6 +1,6 @@ -import { baseAxios } from "./api"; +import { axiosInstance } from "./api"; -interface propTypes { +interface GetArticleParams { page: number; pageSize: number; orderBy: string; @@ -26,7 +26,7 @@ interface Articles { totalCount: number; } -export type GetArticleType = (prop: propTypes) => Promise; +export type GetArticleType = (prop: GetArticleParams) => Promise; const getArticle: GetArticleType = async ({ page, @@ -35,11 +35,12 @@ const getArticle: GetArticleType = async ({ keyword, }) => { try { - const response = await baseAxios.get(`articles`, { + const { data } = await axiosInstance.get(`articles`, { params: { page, pageSize, orderBy, keyword }, }); - return response.data; + return data; } catch (error) { + console.error("APP ERROR: ", error); if (error instanceof Error) { throw new Error(`게시글을 가져오는 데 실패했습니다: ${error.message}`); } diff --git a/hooks/useSetNumberOfItemsToShow.ts b/hooks/useSetNumberOfItemsToShow.ts index 4ab1b071d..ff346cab6 100644 --- a/hooks/useSetNumberOfItemsToShow.ts +++ b/hooks/useSetNumberOfItemsToShow.ts @@ -1,13 +1,12 @@ import { useEffect, useState } from "react"; import { TABLET_WIDTH, MOBILE_WIDTH } from "@/constants/screenSizes"; - -interface propType { +interface PropType { desktop: number; tablet: number; mobile: number; } -type useSetNumOfItemsToShowType = (prop: propType) => number; +type useSetNumOfItemsToShowType = (prop: PropType) => number; const useSetNumOfItemsToShow: useSetNumOfItemsToShowType = ({ desktop, diff --git a/pageComponents/boards/BestPost/components/PostElement/index.tsx b/pageComponents/boards/BestPost/components/PostElement/index.tsx index 7a3e93c90..defad7fc3 100644 --- a/pageComponents/boards/BestPost/components/PostElement/index.tsx +++ b/pageComponents/boards/BestPost/components/PostElement/index.tsx @@ -19,8 +19,11 @@ interface PostType { }; } -const PostElement = ({ post }: { post: PostType }) => { - const { title, image, likeCount, updatedAt, writer } = post; +const PostElement = ({ + post: { title, image, likeCount, updatedAt, writer }, +}: { + post: PostType; +}) => { const postingDate = formatTime(updatedAt); return ( From 20934c637c3042999b874d752ef6feddc94023a1 Mon Sep 17 00:00:00 2001 From: CHAE Date: Tue, 4 Jun 2024 19:58:50 +0900 Subject: [PATCH 02/13] =?UTF-8?q?=E2=9C=A8=20Feat:=20=EA=B8=80=EC=93=B0?= =?UTF-8?q?=EA=B8=B0=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EB=94=94=EC=9E=90?= =?UTF-8?q?=EC=9D=B8=201=EC=B0=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/Inputs/CustomFileInput/index.tsx | 75 ++ .../Inputs/CustomFileInput/style.module.css | 97 ++ components/Inputs/CustomInput/index.tsx | 39 + .../Inputs/CustomInput/style.module.css | 31 + components/Inputs/CustomTextArea/index.tsx | 35 + .../Inputs/CustomTextArea/style.module.css | 31 + images/ic_X_for_img.png | Bin 0 -> 578 bytes images/ic_plus.png | Bin 0 -> 316 bytes package-lock.json | 1186 ++++++++++++++++- package.json | 3 + pageComponents/boards/SearchPost/index.tsx | 10 +- pages/newArticle/index.tsx | 35 + postcss.config.js | 6 + styles/globals.css | 24 +- tailwind.config.js | 14 + 15 files changed, 1556 insertions(+), 30 deletions(-) create mode 100644 components/Inputs/CustomFileInput/index.tsx create mode 100644 components/Inputs/CustomFileInput/style.module.css create mode 100644 components/Inputs/CustomInput/index.tsx create mode 100644 components/Inputs/CustomInput/style.module.css create mode 100644 components/Inputs/CustomTextArea/index.tsx create mode 100644 components/Inputs/CustomTextArea/style.module.css create mode 100644 images/ic_X_for_img.png create mode 100644 images/ic_plus.png create mode 100644 pages/newArticle/index.tsx create mode 100644 postcss.config.js create mode 100644 tailwind.config.js diff --git a/components/Inputs/CustomFileInput/index.tsx b/components/Inputs/CustomFileInput/index.tsx new file mode 100644 index 000000000..058be261d --- /dev/null +++ b/components/Inputs/CustomFileInput/index.tsx @@ -0,0 +1,75 @@ +import { useRef, useState, useEffect, ChangeEvent } from "react"; +import plusIcon from "@/images/ic_plus.png"; +import deleteImgButton from "@/images/ic_X_for_img.png"; +import Image from "next/image"; +import styles from "./style.module.css"; + +interface PropType { + value?: File | null; + onChange?: (e: ChangeEvent) => void; + onDelete: () => void; + name: string; +} + +const CustomFileInput = ({ value, onChange, onDelete, name }: PropType) => { + const [preview, setPreview] = useState(""); + const inputRef = useRef(null); + + useEffect(() => { + if (!value) return; + const nextPreview = URL.createObjectURL(value); + setPreview(nextPreview); + + return () => { + setPreview(""); + URL.revokeObjectURL(nextPreview); + }; + }, [value]); + + const handleClearClick = () => { + const inputNode = inputRef.current; + if (!inputNode) return; + inputNode.value = ""; + onDelete(); + }; + + return ( +
+ +
+ + + {value && ( +
+ 이미지 미리보기 + 이미지 삭제 +
+ )} +
+
+ ); +}; + +export default CustomFileInput; diff --git a/components/Inputs/CustomFileInput/style.module.css b/components/Inputs/CustomFileInput/style.module.css new file mode 100644 index 000000000..85de2fcc7 --- /dev/null +++ b/components/Inputs/CustomFileInput/style.module.css @@ -0,0 +1,97 @@ +/* 이미지 인풋 */ +.container { + display: flex; + flex-direction: column; + gap: 1.2rem; + height: 28.2rem; +} +.container label { + font-size: 1.8rem; + font-weight: 700; + line-height: 2.1rem; + color: var(--coolGray800); +} + +.content { + display: flex; + height: 28.2rem; + gap: 2.4rem; +} + +.fileInput { + display: none; +} + +.btn_upload { + width: 28.2rem; + height: 100%; + background-color: var(--coolGray100); + border: none; + border-radius: 1.2rem; + cursor: pointer; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 1.2rem; +} +.btn_upload:hover { + background-color: white; + color: black; +} +.btn_upload span { + font-size: 1.6rem; + font-weight: 400; + line-height: 2.4rem; +} +.preview_section { + width: 28.2rem; + height: 100%; + border-radius: 1.2rem; + background-color: var(--coolGray100); + position: relative; +} +.image_preview { + width: 100%; + height: 100%; +} + +.preview_delete_btn { + position: absolute; + top: 1rem; + right: 1rem; + cursor: pointer; +} + +@media (max-width: 744px) { + .content { + gap: 1.6rem; + height: 16.2rem; + } + .btn_upload { + width: 16.2rem; + } + .preview_section { + width: 16.2rem; + } +} + +@media (max-width: 375px) { + + .content { + gap: 0.8rem; + height: 16.8rem; + } + .btn_upload { + width: 16.8rem; + } + .preview_section { + width: 16.8rem; + } + .container label { + font-size: 1.4rem; + } + .container { + gap: 1.6rem; + } +} diff --git a/components/Inputs/CustomInput/index.tsx b/components/Inputs/CustomInput/index.tsx new file mode 100644 index 000000000..0f84bdb35 --- /dev/null +++ b/components/Inputs/CustomInput/index.tsx @@ -0,0 +1,39 @@ +import { ChangeEvent } from "react"; +import styles from "./style.module.css"; + +interface PropType { + label: string; + placeholder: string; + value?: string; + onChange?: (event: ChangeEvent) => void; + id: string; + name: string; + type?: string; +} + +const CustomInput = ({ + label, + placeholder, + value, + onChange, + id, + name, + type = "text", +}: PropType) => { + return ( + //일반 +
+ + +
+ ); +}; + +export default CustomInput; diff --git a/components/Inputs/CustomInput/style.module.css b/components/Inputs/CustomInput/style.module.css new file mode 100644 index 000000000..090077ead --- /dev/null +++ b/components/Inputs/CustomInput/style.module.css @@ -0,0 +1,31 @@ +.container { + display: flex; + flex-direction: column; + gap: 1.2rem; +} +.container label { + font-size: 1.8rem; + font-weight: 700; + line-height: 2.1rem; + color: var(--coolGray800); +} + +.container input { + height: 5.6rem; + border-radius: 1.2rem; + border: none; + background-color: var(--coolGray100); + padding: 1.6rem 2.4rem; + font-size: 1.6rem; + font-weight: 400; + line-height: 2.4rem; +} + +@media (max-width: 375px) { + .container label { + font-size: 1.4rem; + } + .container { + gap: 1.6rem; + } +} diff --git a/components/Inputs/CustomTextArea/index.tsx b/components/Inputs/CustomTextArea/index.tsx new file mode 100644 index 000000000..224499627 --- /dev/null +++ b/components/Inputs/CustomTextArea/index.tsx @@ -0,0 +1,35 @@ +import { ChangeEvent } from "react"; +import styles from "./style.module.css"; + +interface PropType { + label: string; + placeholder: string; + value?: string; + onChange?: (event: ChangeEvent) => void; + id: string; + name: string; +} + +const CustomTextArea = ({ + label, + placeholder, + value, + onChange, + id, + name, +}: PropType) => { + return ( +
+ +