Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[오정민] sprint11 #319

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
f89780b
chore: Airbnb ESLint 규칙 적용
ojm51 Aug 20, 2024
3421769
fix: <ul> 안에 있는 <div>를 <li>로 수정
ojm51 Aug 20, 2024
0ade27a
chore: day.js 추가
ojm51 Aug 20, 2024
461d565
fix: 날짜 사용 함수에 day.js 라이브러리 적용
ojm51 Aug 20, 2024
f3bffcb
chore: react hook form 라이브러리 추가
ojm51 Aug 21, 2024
85a0e50
rename: 페이지 파일 경로 수정
ojm51 Aug 21, 2024
dd7a6e7
feat: 랜딩 페이지 생성
ojm51 Aug 21, 2024
99636be
feat: 로그인 페이지 생성
ojm51 Aug 21, 2024
a1e71c0
feat: 회원가입 페이지 생성
ojm51 Aug 21, 2024
d8d41f2
feat: 로그인 및 회원가입 페이지에서 네비게이션 바 제외
ojm51 Aug 21, 2024
ffe4d46
design: 로그인 및 회원가입 페이지 input 컴포넌트로 변경
ojm51 Aug 21, 2024
97b2095
feat: 회원가입 페이지에 react-hook-form 적용
ojm51 Aug 22, 2024
80d5760
feat: 로그인 페이지에 react-hook-form 적용
ojm51 Aug 22, 2024
643642b
feat: 회원가입 구현
ojm51 Aug 23, 2024
5d214d3
feat: 로그인 구현
ojm51 Aug 23, 2024
fdb93ce
feat: 로그인 여부에 따라 네비게이션 바 변경
ojm51 Aug 23, 2024
1ed727b
design: BigLogo 컴포넌트 생성
ojm51 Aug 23, 2024
fe9c4b1
feat: 비밀번호 보이기 및 숨기기 기능 추가
ojm51 Aug 23, 2024
4bb270d
design: 회원가입 및 로그인 페이지 디자인 추가
ojm51 Aug 23, 2024
3f6e95f
design: 랜딩 페이지 일부 디자인 추가
ojm51 Aug 25, 2024
2676d55
chore: 허용 도메인 임시 수정
ojm51 Aug 25, 2024
319f21c
feat: api 경로를 변수로 치환
ojm51 Aug 26, 2024
dfc0519
fix: 컴포넌트 언마운트 시 프리뷰 이미지 revoke
ojm51 Aug 26, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
@@ -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"
}
}
3 changes: 2 additions & 1 deletion .prettierrc
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{
"plugins": ["prettier-plugin-tailwindcss"]
"plugins": ["prettier-plugin-tailwindcss"],
"singleQuote": false
}
Binary file added assets/images/ic_google.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/ic_kakao.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
40 changes: 3 additions & 37 deletions components/AddComment.tsx
Original file line number Diff line number Diff line change
@@ -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";
Expand All @@ -9,8 +10,8 @@ const INPUT_CONTENT = [
{
name: "content",
label: "댓글달기",
type: "textarea",
placeholder: "댓글을 입력해주세요",
isTextArea: true,
},
];

Expand All @@ -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),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

피드백대로 잘 바꾸어 주셨네요 !!!

inputValue,
{
headers: {
Expand All @@ -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);
Expand Down Expand Up @@ -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);
// }
// }
4 changes: 3 additions & 1 deletion components/AllArticleList/AllArticle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@ function AllArticle({ article }: AllArticleProps) {
height={24}
/>
<h5 className={styles.nickname}>{writer.nickname}</h5>
<h5 className={styles.createdAt}>{formatDate(createdAt)}</h5>
<h5 className={styles.createdAt}>
{formatDate(new Date(createdAt))}
</h5>
</div>
<div className={styles.likeWrapper}>
<button onClick={handleLikeButtonClick}>
Expand Down
2 changes: 1 addition & 1 deletion components/BestArticleList/BestArticle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ function BestArticle({ article }: BestArticleProps) {
<h5 className={styles.likeCount}>{likeCount}</h5>
</div>
</div>
<h5 className={styles.createdAt}>{formatDate(createdAt)}</h5>
<h5 className={styles.createdAt}>{formatDate(new Date(createdAt))}</h5>
</div>
</Link>
);
Expand Down
25 changes: 25 additions & 0 deletions components/BigLogo.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<Link className="flex items-center justify-center gap-6" href="/">
<Image
src={logoIcon}
alt="판다마켓 로고 이미지"
width={104}
height={104}
/>
<Image
src={logoText}
alt="판다마켓 로고 이미지"
width={266}
height={90}
/>
</Link>
);
}

export default BigLogo;
19 changes: 19 additions & 0 deletions components/Buttons/FormButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
interface FormButtonProps {
isButtonDisabled: boolean;
text: string;
}

function FormButton({ isButtonDisabled, text }: FormButtonProps) {
return (
<button
className="w-full rounded-full bg-brand-blue py-3 text-xl font-semibold text-gray-100 disabled:bg-gray-400"
type="submit"
value={text}
disabled={isButtonDisabled}
>
{text}
</button>
);
}

export default FormButton;
8 changes: 4 additions & 4 deletions components/CommentList/CommentList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,22 @@ function CommentList({ commentList: comments }: CommentListProps) {
{!!comments.length ? (
<ul className="comment-lists">
{comments.map((comment: IComment) => (
<div key={comment.id}>
<li key={comment.id}>
<Comment comment={comment} />
</div>
</li>
))}
</ul>
) : (
// TODO: EmptyContent 컴포넌트 빼내기 가능
<div className="flex flex-col items-center justify-center">
<Image
src={replayEmptyImage}
alt="아직 문의가 없습니다"
alt="아직 댓글이 없습니다"
width={200}
height={200}
/>
<div className="text-base font-normal text-gray-400">
아직 문의가 없습니다.
아직 댓글이 없습니다.
</div>
</div>
)}
Expand Down
2 changes: 1 addition & 1 deletion components/DetailArticle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ function DetailArticle({ article }: DetailArticleProps) {
{writer.nickname || "Anonymous"}
</h5>
<h5 className="text-sm font-normal text-gray-400">
{formatDate(createdAt)}
{formatDate(new Date(createdAt))}
</h5>
</div>
</div>
Expand Down
22 changes: 22 additions & 0 deletions components/EasyLogin/EasyLogin.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<div className="mb-6 mt-6 flex items-center justify-between rounded-lg bg-[#E6F2FF] px-6 py-4 text-base font-medium text-gray-800">
간편 로그인하기
<div className="flex items-center justify-center gap-4">
<Link href="https://www.google.com/">
<Image src={googleIcon} alt="구글 아이콘" width={42} height={42} />
</Link>
<Link href="https://www.kakaocorp.com/page/">
<Image src={kakaoIcon} alt="카카오톡 아이콘" width={42} height={42} />
</Link>
</div>
</div>
);
}

export default EasyLogin;
10 changes: 9 additions & 1 deletion components/Inputs/FileInput.tsx
Original file line number Diff line number Diff line change
@@ -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";
Expand Down Expand Up @@ -26,6 +26,14 @@ function FileInput({ name, label, onChange }: FileInputProps) {
setPreview("");
};

useEffect(() => {
return () => {
if (preview) {
URL.revokeObjectURL(preview);
}
};
}, [preview]);

return (
<div className="file-input-wrapper">
<div className="mb-3 text-lg font-bold text-gray-800">{label}</div>
Expand Down
58 changes: 58 additions & 0 deletions components/Inputs/FormPasswordInput.tsx
Original file line number Diff line number Diff line change
@@ -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<Record<string, any>>;
}

function FormPasswordInput({ content, register }: FormPasswordInputProps) {
const { name, label, placeholder } = content;

const [isPasswordShow, setIsPasswordShow] = useState(false);
const handlePasswordShowButtonClick = () => {
setIsPasswordShow((prevIsPasswordShow) => !prevIsPasswordShow);
};

return (
<div className="mb-6 flex flex-col items-start justify-start">
<label className="mb-3 text-lg font-bold text-gray-800" htmlFor={name}>
{label}
</label>

<input
className="w-full rounded-xl bg-gray-100 px-6 py-4"
id={name}
type="password"
placeholder={placeholder}
{...register}
/>
<button
className="password-show-btn"
type="button"
value="비밀번호 보이거나 가리기"
onClick={handlePasswordShowButtonClick}
>
<Image
className="password-show-icon"
src={isPasswordShow ? passwordShowIcon : passwordHideIcon}
alt="비밀번호를 보여주는 눈 모양 아이콘"
width={24}
height={24}
/>
</button>
</div>
);
}

export default FormPasswordInput;
35 changes: 35 additions & 0 deletions components/Inputs/FormTextInput.tsx
Original file line number Diff line number Diff line change
@@ -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<Record<string, any>>;
}

function FormTextInput({ content, register }: FormTextInputProps) {
const { name, label, type, placeholder } = content;

return (
<div className="mb-6 flex flex-col items-start justify-start">
<label className="mb-3 text-lg font-bold text-gray-800" htmlFor={name}>
{label}
</label>

<input
className="w-full rounded-xl bg-gray-100 px-6 py-4"
id={name}
type={type}
placeholder={placeholder}
{...register}
/>
</div>
);
}

export default FormTextInput;
12 changes: 6 additions & 6 deletions components/Inputs/TextInput.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
interface Content {
name: string;
label: string;
type: string;
placeholder: string;
isTextArea: boolean;
}

interface TextInputProps {
Expand All @@ -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<HTMLInputElement | HTMLTextAreaElement>,
Expand All @@ -26,20 +26,20 @@ function TextInput({ content, onChange }: TextInputProps) {
{label}
</label>

{!isTextArea ? (
<input
{type === "textarea" ? (
<textarea
className="w-full rounded-xl bg-gray-100 px-6 py-4"
id={name}
name={name}
type="text"
placeholder={placeholder}
onChange={handleTextInputChange}
/>
) : (
<textarea
<input
className="w-full rounded-xl bg-gray-100 px-6 py-4"
id={name}
name={name}
type={type}
placeholder={placeholder}
onChange={handleTextInputChange}
/>
Expand Down
Loading
Loading