diff --git a/.eslintrc.json b/.eslintrc.json index bffb357a7..cce2d8873 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,3 +1,9 @@ { - "extends": "next/core-web-vitals" + "extends": ["next/core-web-vitals", "airbnb", "plugin:prettier/recommended"], + "rules": { + "quotes": ["error", "double"], + "prettier/prettier": ["error", { "singleQuote": false }], + "react/react-in-jsx-scope": "off", + "import/extensions": "off" + } } diff --git a/.prettierrc b/.prettierrc index b4bfed357..51a02cc08 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,3 +1,4 @@ { - "plugins": ["prettier-plugin-tailwindcss"] + "plugins": ["prettier-plugin-tailwindcss"], + "singleQuote": false } diff --git a/assets/images/ic_google.png b/assets/images/ic_google.png new file mode 100644 index 000000000..d97024347 Binary files /dev/null and b/assets/images/ic_google.png differ diff --git a/assets/images/ic_kakao.png b/assets/images/ic_kakao.png new file mode 100644 index 000000000..2a6cb101d Binary files /dev/null and b/assets/images/ic_kakao.png differ diff --git a/components/AddComment.tsx b/components/AddComment.tsx index 24fdeeee3..c8bafbe6b 100644 --- a/components/AddComment.tsx +++ b/components/AddComment.tsx @@ -1,6 +1,7 @@ import { Dispatch, SetStateAction, useState } from "react"; import axios from "@/lib/axios"; import { IComment } from "@/types/comment"; +import { API_PATH } from "@/lib/path"; import TextInput from "./Inputs/TextInput"; import AddButton from "./Buttons/AddButton"; @@ -9,8 +10,8 @@ const INPUT_CONTENT = [ { name: "content", label: "댓글달기", + type: "textarea", placeholder: "댓글을 입력해주세요", - isTextArea: true, }, ]; @@ -37,7 +38,7 @@ function AddComment({ id, setCommentList }: AddCommentProps) { let newComment: IComment; try { const response = await axios.post( - `/articles/${id}/comments`, + API_PATH.articleComments(id), inputValue, { headers: { @@ -47,7 +48,6 @@ function AddComment({ id, setCommentList }: AddCommentProps) { ); newComment = response.data ?? []; - console.log("post succeed: ", newComment); setCommentList((prevCommentList) => [newComment, ...prevCommentList]); } catch (error) { console.error("댓글 등록 중 오류가 발생했습니다: ", error); @@ -81,37 +81,3 @@ function AddComment({ id, setCommentList }: AddCommentProps) { } export default AddComment; - -// const [inputValue, setInputValue] = useState({ -// content: "", -// }); -// const [isFormComplete, setIsFormComplete] = useState(false); - -// const handleValueChange = (name: string, value: string) => { -// setInputValue((prevValues) => ({ -// ...prevValues, -// [name]: value, -// })); -// setIsFormComplete(value.trim() !== ""); -// }; - -// async function postComment() { -// const accessToken = -// "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MjUsInNjb3BlIjoiYWNjZXNzIiwiaWF0IjoxNzIzNzczNzEzLCJleHAiOjE3MjM3NzU1MTMsImlzcyI6InNwLXBhbmRhLW1hcmtldCJ9.heZocGCQOejK4JPnWgWzJ438vW1sE2RAsj5d6ZHIhbc"; - -// let newComment: IComment; -// try { -// const data = { -// ...inputValue, -// }; -// const response = await axios.post(`/articles/${id}/comments`, data, { -// headers: { -// Authorization: `Bearer ${accessToken}`, -// }, -// }); -// newComment = response.data ?? []; -// setCommentList((prevCommentList) => [newComment, ...prevCommentList]); -// } catch (error) { -// console.error("댓글 등록 중 오류가 발생했습니다: ", error); -// } -// } diff --git a/components/AllArticleList/AllArticle.tsx b/components/AllArticleList/AllArticle.tsx index bf830fe76..db6721b5e 100644 --- a/components/AllArticleList/AllArticle.tsx +++ b/components/AllArticleList/AllArticle.tsx @@ -45,7 +45,9 @@ function AllArticle({ article }: AllArticleProps) { height={24} />
{writer.nickname}
-
{formatDate(createdAt)}
+
+ {formatDate(new Date(createdAt))} +
-
{formatDate(createdAt)}
+
{formatDate(new Date(createdAt))}
); diff --git a/components/BigLogo.tsx b/components/BigLogo.tsx new file mode 100644 index 000000000..1e8217d05 --- /dev/null +++ b/components/BigLogo.tsx @@ -0,0 +1,25 @@ +import Link from "next/link"; +import Image from "next/image"; +import logoIcon from "@/assets/images/ic_logo_icon.png"; +import logoText from "@/assets/images/ic_logo_text.png"; + +function BigLogo() { + return ( + + 판다마켓 로고 이미지 + 판다마켓 로고 이미지 + + ); +} + +export default BigLogo; diff --git a/components/Buttons/FormButton.tsx b/components/Buttons/FormButton.tsx new file mode 100644 index 000000000..732b267ae --- /dev/null +++ b/components/Buttons/FormButton.tsx @@ -0,0 +1,19 @@ +interface FormButtonProps { + isButtonDisabled: boolean; + text: string; +} + +function FormButton({ isButtonDisabled, text }: FormButtonProps) { + return ( + + ); +} + +export default FormButton; diff --git a/components/CommentList/CommentList.tsx b/components/CommentList/CommentList.tsx index ec88d49dc..6db61abb5 100644 --- a/components/CommentList/CommentList.tsx +++ b/components/CommentList/CommentList.tsx @@ -14,9 +14,9 @@ function CommentList({ commentList: comments }: CommentListProps) { {!!comments.length ? ( ) : ( @@ -24,12 +24,12 @@ function CommentList({ commentList: comments }: CommentListProps) {
아직 문의가 없습니다
- 아직 문의가 없습니다. + 아직 댓글이 없습니다.
)} diff --git a/components/DetailArticle.tsx b/components/DetailArticle.tsx index e8788542a..9a00dac13 100644 --- a/components/DetailArticle.tsx +++ b/components/DetailArticle.tsx @@ -47,7 +47,7 @@ function DetailArticle({ article }: DetailArticleProps) { {writer.nickname || "Anonymous"}
- {formatDate(createdAt)} + {formatDate(new Date(createdAt))}
diff --git a/components/EasyLogin/EasyLogin.tsx b/components/EasyLogin/EasyLogin.tsx new file mode 100644 index 000000000..7166d3fa9 --- /dev/null +++ b/components/EasyLogin/EasyLogin.tsx @@ -0,0 +1,22 @@ +import Link from "next/link"; +import Image from "next/image"; +import googleIcon from "@/assets/images/ic_google.png"; +import kakaoIcon from "@/assets/images/ic_kakao.png"; + +function EasyLogin() { + return ( +
+ 간편 로그인하기 +
+ + 구글 아이콘 + + + 카카오톡 아이콘 + +
+
+ ); +} + +export default EasyLogin; diff --git a/components/Inputs/FileInput.tsx b/components/Inputs/FileInput.tsx index df2b154d5..1a634abb0 100644 --- a/components/Inputs/FileInput.tsx +++ b/components/Inputs/FileInput.tsx @@ -1,4 +1,4 @@ -import { useState } from "react"; +import { useEffect, useState } from "react"; import Image from "next/image"; import plusIcon from "@/assets/images/ic_plus.png"; @@ -26,6 +26,14 @@ function FileInput({ name, label, onChange }: FileInputProps) { setPreview(""); }; + useEffect(() => { + return () => { + if (preview) { + URL.revokeObjectURL(preview); + } + }; + }, [preview]); + return (
{label}
diff --git a/components/Inputs/FormPasswordInput.tsx b/components/Inputs/FormPasswordInput.tsx new file mode 100644 index 000000000..e11e2322b --- /dev/null +++ b/components/Inputs/FormPasswordInput.tsx @@ -0,0 +1,58 @@ +import { useState } from "react"; +import { UseFormRegister } from "react-hook-form"; +import Image from "next/image"; +import passwordHideIcon from "@/assets/images/ic_password_hide.png"; +import passwordShowIcon from "@/assets/images/ic_password_show.png"; + +interface Content { + name: string; + label: string; + type?: string; + placeholder: string; +} + +interface FormPasswordInputProps { + content: Content; + register: UseFormRegister>; +} + +function FormPasswordInput({ content, register }: FormPasswordInputProps) { + const { name, label, placeholder } = content; + + const [isPasswordShow, setIsPasswordShow] = useState(false); + const handlePasswordShowButtonClick = () => { + setIsPasswordShow((prevIsPasswordShow) => !prevIsPasswordShow); + }; + + return ( +
+ + + + +
+ ); +} + +export default FormPasswordInput; diff --git a/components/Inputs/FormTextInput.tsx b/components/Inputs/FormTextInput.tsx new file mode 100644 index 000000000..c62a6ee6d --- /dev/null +++ b/components/Inputs/FormTextInput.tsx @@ -0,0 +1,35 @@ +import { UseFormRegister } from "react-hook-form"; + +interface Content { + name: string; + label: string; + type: string; + placeholder: string; +} + +interface FormTextInputProps { + content: Content; + register: UseFormRegister>; +} + +function FormTextInput({ content, register }: FormTextInputProps) { + const { name, label, type, placeholder } = content; + + return ( +
+ + + +
+ ); +} + +export default FormTextInput; diff --git a/components/Inputs/TextInput.tsx b/components/Inputs/TextInput.tsx index ee5c48af5..eb006e863 100644 --- a/components/Inputs/TextInput.tsx +++ b/components/Inputs/TextInput.tsx @@ -1,8 +1,8 @@ interface Content { name: string; label: string; + type: string; placeholder: string; - isTextArea: boolean; } interface TextInputProps { @@ -11,7 +11,7 @@ interface TextInputProps { } function TextInput({ content, onChange }: TextInputProps) { - const { name, label, placeholder, isTextArea } = content; + const { name, label, type, placeholder } = content; const handleTextInputChange = ( e: React.ChangeEvent, @@ -26,20 +26,20 @@ function TextInput({ content, onChange }: TextInputProps) { {label} - {!isTextArea ? ( - ) : ( -