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 #313

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 2 additions & 0 deletions next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ const nextConfig = {
"sprint-fe-project.s3.ap-northeast-2.amazonaws.com",
"images.samsung.com",
"example.com",
"flexible.img.hani.co.kr",
"via.placeholder.com",
],
},
};
Expand Down
18 changes: 17 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
"axios": "^1.7.3",
"next": "14.2.5",
"react": "^18",
"react-dom": "^18"
"react-dom": "^18",
"react-hook-form": "^7.52.2"
},
"devDependencies": {
"@types/node": "^20",
Expand Down
Binary file modified public/images/icon/ic_null_user_profile_image.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions src/components/DetailBoard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,15 @@ function Product() {
const res = await axios.get(`/articles/${id}`);
const nextProduct = res.data;
setProduct(nextProduct);
setLoading(false);
} catch (error) {
console.error(`유효하지 않은 주소입니다.`);
alert(`유효하지 않은 주소입니다.`);
router.replace(`/board`);
}
}

useEffect(() => {
getProduct(id);
setLoading(false);
}, [id]);

if (loading) {
Expand Down
34 changes: 14 additions & 20 deletions src/components/DetailBoardComments.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,24 @@ interface ItemsListType {
function DetailBoardComments() {
const [comments, setComments] = useState<ItemsListType[]>([]);
const [loading, setLoading] = useState(true);
const [values, setValues] = useState("");
const [commentsValues, setCommentsValues] = useState("");
const [pass, setPass] = useState(false);
const router = useRouter();
const id = Number(router.query["id"]);

// 게시판 댓글 데이터 가져오기
async function getProduct(id: number) {
const res = await axios.get(`/articles/${id}/comments?limit=50`);
const nextComments = res.data.list;
console.log(nextComments);
setComments(nextComments);
try {
const res = await axios.get(`/articles/${id}/comments?limit=50`);
const nextComments = res.data.list;
setComments(nextComments);
setLoading(false);
} catch (error) {
alert("댓글 데이터 불러오기 실패");
}
}
useEffect(() => {
getProduct(id);
setLoading(false);
}, [id]);

const onClickReturn = () => {
Expand All @@ -47,13 +50,14 @@ function DetailBoardComments() {
// 댓글 인풋의 입력값 파악
const handleInputChange = (e: ChangeEvent<HTMLTextAreaElement>) => {
const { value } = e.target;
setValues(value);
setCommentsValues(value);
};

// 테스트를 위해 추가한 동작
// TODO: 스프린트 미션에 API POST 관련 기능 요구 시 추가 예정, 현재는 테스트를 위한 코드
const handleSubmit = (e: FormEvent<HTMLButtonElement>) => {
if (commentsValues.length <= 0) return;
e.preventDefault();
console.log(values);
console.log(commentsValues);
};

// 댓글 작성한 시간 변환 함수
Expand All @@ -78,16 +82,6 @@ function DetailBoardComments() {
}
};

// 입력값 감지 후 조건 충족 시 등록 버튼 활성화
useEffect(() => {
function validation() {
const valueCheck = values.length > 0;
return valueCheck;
}
const isValid = validation();
setPass(isValid);
}, [values]);

if (loading) {
return <div>Loading...</div>;
}
Expand All @@ -104,7 +98,7 @@ function DetailBoardComments() {
/>
<div className={S.buttonWrapper}>
<button
className={`${S.commentSubmitButton} ${pass ? S.pass : ""}`}
className={`${S.commentSubmitButton} ${commentsValues.length > 0 ? S.pass : ""}`}
onClick={handleSubmit}
>
등록
Expand Down
31 changes: 31 additions & 0 deletions src/components/NavBar.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@
background-color: var(--blue3);
}

.userProfileIcon {
position: relative;
width: 40px;
height: 40px;
}

.navLink {
display: flex;
width: 109px;
Expand All @@ -77,6 +83,23 @@
color: var(--blue);
}

.dropDown {
position: absolute;
top: 48px;
left: -100px;
border: 2px solid var(--gray300);
border-radius: 8px;
background-color: #fff;
font-size: 16px;
font-weight: 400;
padding: 16px 0px 16px 0px;
display: flex;
justify-content: center;
align-items: center;
width: 139px;
height: 51px;
}

@media screen and (max-width: 1199px) and (min-width: 768px) {
.headerNav {
padding: 0 24px;
Expand All @@ -86,6 +109,10 @@
width: 153px;
height: 51px;
}
.userProfileIcon {
width: 32px;
height: 32px;
}
}

@media screen and (max-width: 767px) {
Expand Down Expand Up @@ -121,4 +148,8 @@
.itemPage {
color: var(--blue);
}
.userProfileIcon {
width: 32px;
height: 32px;
}
}
40 changes: 37 additions & 3 deletions src/components/NavBar.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,24 @@
import Link from "next/link";
import Image from "next/image";
import S from "@/components/NavBar.module.css";
import { useEffect, useState } from "react";
import { useRouter } from "next/router";

function NavBar() {
const [isLoggedIn, setIsLoggedIn] = useState(false);
const [isOpen, setIsOpen] = useState(false);
const router = useRouter();
const handleLogout = () => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

함수 이름이 handleLogout으로 되어있는데 동작하는 코드는 로그아웃이랑 관련이 없는 코드인것같아요.
logout ui를 열었다 닫는 용도인것같아서 함수 이름을 다른 이름으로 바꿔보는건 어떨까요???

함수가 어떤 동작을 하느냐로 생각해보고 이름지으면 좋습니다 :-)

setIsOpen(!isOpen);
};
const onClickLogout = () => {
window.localStorage.removeItem("accessToken");
router.reload();
Copy link
Collaborator

Choose a reason for hiding this comment

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

요구사항에 로그아웃 후에 페이지가 새로고침 되어야 한다 면 무방하지만
로그아웃 이후에 프로필이 로그인으로 안바껴서 새로고침 하는거라면

localStorage는 지역state 밖이라 컴포넌트에선 감지 안되는 걸 염두해 두시고 방법을 찾아보세요 :-)

};
useEffect(() => {
const token = localStorage.getItem("accessToken");
setIsLoggedIn(Boolean(token));
}, []);
return (
<header className={S.header}>
<div className={S.headerNav}>
Expand Down Expand Up @@ -32,9 +48,27 @@ function NavBar() {
</Link>
</div>
</div>
<Link href="/login" className={S.loginBtn}>
로그인
</Link>
{isLoggedIn ? (
Copy link
Collaborator

Choose a reason for hiding this comment

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

중첩된 삼항연산자는 코드를 읽는 흐름이 좋지않게 되어서 렌더 단위를 함수로 만들어서 JSX를 반환하거나
if-elseif 문으로 보기쉽게 만드는것도 좋을것같네요

 const renderLoggedIn = () => (
    <div className={S.userProfileIcon}>
      <Image
        src="/images/icon/ic_null_user_profile_image.png"
        fill
        alt="유저 프로필 아이콘"
        onClick={handleLogout}
      />
      {isOpen && (
        <div className={S.dropDown} onClick={onClickLogout}>
          로그아웃
        </div>
      )}
    </div>
  );

  const renderLoggedOut = () => (
    <Link href="/login" className={S.loginBtn}>
      로그인
    </Link>
  );

  return isLoggedIn ? renderLoggedIn() : renderLoggedOut();

<div className={S.userProfileIcon}>
<Image
src="/images/icon/ic_null_user_profile_image.png"
fill
alt="유저 프로필 아이콘"
onClick={handleLogout}
/>
{isOpen ? (
<div className={S.dropDown} onClick={onClickLogout}>
로그아웃
</div>
) : (
<></>
)}
</div>
) : (
<Link href="/login" className={S.loginBtn}>
로그인
</Link>
)}
</div>
</header>
);
Expand Down
7 changes: 1 addition & 6 deletions src/components/ProductComments.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,6 @@ import S from "@/components/ProductComments.module.css";
const PLACEHOLDERTEXT =
"개인정보를 공유 및 요청하거나, 명예 훼손, 무단 광고, 불법 정보 유포시 모니터링 후 삭제될 수 있으며, 이에 대한 민형사상 책임은 게시자에게 있습니다.";

interface ButtonProps {
$pass?: boolean;
}

interface ItemsListType<T> {
list: T[];
}
Expand All @@ -33,10 +29,9 @@ function ProductComments() {
setValues(value);
};

// 테스트를 위해 추가한 동작
// TODO: 스프린트 미션에 API POST 관련 기능 요구 시 추가 예정, 현재는 테스트를 위한 코드
const handleSubmit = (e: FormEvent<HTMLButtonElement>) => {
e.preventDefault();
console.log(values);
};

// 댓글 작성한 시간 변환 함수
Expand Down
5 changes: 4 additions & 1 deletion src/pages/_app.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import NavBar from "@/components/NavBar";
import "@/styles/globals.css";
import type { AppProps } from "next/app";
import { useRouter } from "next/router";

export default function App({ Component, pageProps }: AppProps) {
const router = useRouter();
const noNavBarPages = ["/login", "/register"];
return (
<>
<NavBar />
{!noNavBarPages.includes(router.pathname) && <NavBar />}
<Component {...pageProps} />
</>
);
Expand Down
3 changes: 1 addition & 2 deletions src/pages/addboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ function AddBoard() {
}
};

// 등록 버튼 클릭 시 제출
// TODO: 스프린트 미션에 API POST 관련 기능 요구 시 추가 예정, 현재는 테스트를 위한 코드
const handleSubmit = (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
console.log(values);
Expand All @@ -64,7 +64,6 @@ function AddBoard() {
return;
}
const image = values.images;
console.log(image);

if (!(image instanceof File)) {
console.error("Expected a File object but got:", image);
Expand Down
5 changes: 2 additions & 3 deletions src/pages/additem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ function AddItem() {
const [preview, setPreview] = useState("");
const [tagInput, setTagInput] = useState("");
const [pass, setPass] = useState(false);
console.log(values);

// 이미지 삭제
const onClickImageDelete = () => {
setValues((prevValues) => ({
Expand Down Expand Up @@ -70,7 +70,7 @@ function AddItem() {
setTagInput(e.target.value);
};

// 등록 버튼 클릭 시 제출
// TODO: 스프린트 미션에 API POST 관련 기능 요구 시 추가 예정, 현재는 테스트를 위한 코드
const handleSubmit = (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
console.log(values);
Expand Down Expand Up @@ -103,7 +103,6 @@ function AddItem() {
return;
}
const image = values.images;
console.log(image);

if (!(image instanceof File)) {
console.error("Expected a File object but got:", image);
Expand Down
1 change: 0 additions & 1 deletion src/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ export default function Home() {
<title></title>
</Head>
<div className={S.homeContainer}>
{/* <NavBar /> */}
<header>
<div className={S.headerContentsBackground}>
<div className={S.headerContent}>
Expand Down
Loading
Loading