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

[feat]MyPage React #88

Open
wants to merge 1 commit into
base: jinmo
Choose a base branch
from
Open
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
4 changes: 4 additions & 0 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import PostEditPage from "./routes/PostEditPage";
import SignUpPage from "./routes/SignUpPage";
import PostDetailPage from "./routes/PostDetailPage";
import SignInPage from "./routes/SignInPage";
import MyPage from "./routes/MyPage";

function App() {
return (
Expand All @@ -27,6 +28,9 @@ function App() {
<Route path="/signup" element={<SignUpPage />} />
{/* sign up */}
<Route path="/signin" element={<SignInPage />} />
{/* MyPage */}
<Route path="/mypage" element={<MyPage />} />

</Routes>
<Footer />
</BrowserRouter>
Expand Down
19 changes: 19 additions & 0 deletions src/apis/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,16 @@ export const getUser = async () => {
return response.data;
};

export const getMyPage = async () => {
const response = await instanceWithToken.get("/account/mypage/");
if (response.status === 200) {
console.log("GET USER SUCCESS");
} else {
console.log("[ERROR] error while updating comment");
}
return response.data;
};

// Post 관련 API들
export const getPosts = async () => {
const response = await instance.get("/post/");
Expand Down Expand Up @@ -61,6 +71,15 @@ export const updatePost = async (id, data, navigate) => {
}
};

export const updateMyInfo = async (data) => {
const response = await instanceWithToken.patch(`/account/info/`, data);
if (response.status === 201) {
console.log("POST UPDATE SUCCESS");
} else {
console.log("[ERROR] error while updating post");
}
};

//과제!!
export const deletePost = async (id, navigate) => {
const response = await instanceWithToken.delete(`post/${id}/`)
Expand Down
66 changes: 66 additions & 0 deletions src/components/Comment/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { useEffect, useState } from "react";
import CommentElement from "./CommentElement";
import { createComment, getComments, deleteComment } from "../../apis/api";


const Comment = ({ postId }) => {
const [commentList, setCommentList] = useState([]); // state for comments
const [newContent, setNewContent] = useState(""); // state for new comment

useEffect(() => {
const getCommentsAPI = async () => {
const comments = await getComments(postId);
setCommentList(comments);
};
getCommentsAPI();
}, [postId]);

const handleCommentSubmit = (e) => {
e.preventDefault();
setNewContent("");
createComment({ post: postId, content: newContent });
};

// 과제!!
const handleCommentDelete = async (commentId) => {
const confirmDelete = window.confirm("정말로 댓글을 삭제하시겠습니까?");
if (confirmDelete) {
await deleteComment(commentId);
window.location.reload();
}
};

return (
<div className="w-full mt-5 self-start">
<h1 className="text-3xl font-bold mt-5 mb-3">Comments</h1>
{commentList.map((comment) => {
return (
<div className="w-full flex flex-row" key={comment.id}>
<CommentElement
comment={comment}
handleCommentDelete={handleCommentDelete}
/>
</div>
);
})}
{/* comment form component */}
<form
className="flex items-center justify-center mt-10 gap-2"
onSubmit={handleCommentSubmit}
>
<input
type="text"
value={newContent}
placeholder="댓글을 입력해주세요"
className="input h-14"
onChange={(e) => setNewContent(e.target.value)}
/>
<button type="submit" className="button">
comment
</button>
</form>
</div>
);
};

export default Comment;
139 changes: 139 additions & 0 deletions src/components/EditInput/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
import { Link } from "react-router-dom";
import { useEffect, useState } from "react";
import { updateMyInfo } from "../../apis/api";

export const MyPageInput = ({ content }) => {
const [isEmailEdit, setIsEmailEdit] = useState(false);
const [isUsernameEdit, setIsUsernameEdit] = useState(false);
const [isCollegeEdit, setIsCollegeEdit] = useState(false);
const [isMajorEdit, setIsMajorEdit] = useState(false);
Comment on lines +6 to +9
Copy link

Choose a reason for hiding this comment

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

이 부분의 경우 formData를 처리하는 것처럼 한번에 관리해주는게 좋아요!

Suggested change
const [isEmailEdit, setIsEmailEdit] = useState(false);
const [isUsernameEdit, setIsUsernameEdit] = useState(false);
const [isCollegeEdit, setIsCollegeEdit] = useState(false);
const [isMajorEdit, setIsMajorEdit] = useState(false);
const [isEdit, setIsEdit] = useState({
email : false,
username: false,
college: false,
major: false
})

이런식으로요!

const [formData, setFormData] = useState(content);
Copy link

Choose a reason for hiding this comment

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

굳이 content를 그대로 사용하지 않고, formData에 넣어준 이유가 있을까요?


const handleChange = (e) => {

if (e.target.id === "email" || e.target.id === "username")
{
setFormData({ ...formData, [`user`]: {...formData.user, [e.target.id]: e.target.value} });
}
else setFormData({ ...formData, [e.target.id]: e.target.value });
};
Comment on lines +12 to +19
Copy link

Choose a reason for hiding this comment

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

MyPage 부분에 남긴 comment를 참고한다면 이 부분도 보다 간단하게 바꿀 수 있을거예요!!


const onSubmit = async (e) => {
e.preventDefault();
await updateMyInfo(formData);
setIsEmailEdit(false);
setIsUsernameEdit(false);
setIsCollegeEdit(false);
setIsMajorEdit(false);
};
Comment on lines +21 to +28
Copy link

Choose a reason for hiding this comment

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

updateMyInfo api에 새로고침을 하는 부분이 없는것 같은데, 새로고침이 됐나요??
그리고 만약에 새로고침을 한다면 뒤에 setState는 의미가 없습니다! 어차피 새로고침 하니 알아서 전부 초기 상태로 돌아가기 때문이죠


const onEmailEditClick = async (e) => {
setIsEmailEdit(true);
};

const onUsernameEditClick = async (e) => {
setIsUsernameEdit(true);
};

const onCollegeEditClick = async (e) => {
setIsCollegeEdit(true);
};

const onMajorEditClick = async (e) => {
setIsMajorEdit(true);
};

Comment on lines +30 to +45
Copy link

Choose a reason for hiding this comment

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

우선, 이 부분은 그냥 setState를 활용해서 state를 변경해주는 것이기 때문에 비동기 처리가 아니예요! async를 사용할 필요가 없습니다.
그리고 e를 사용하지 않는다면 굳이 적어둘 필요 없습니다!

또, 이 부분도 isEdit으로 한번에 관리한다면 훨씬 편하겠죠?
만약에 button의 id를 email, username 이런식으로 설정한다고 가정한다면

Suggested change
const onEmailEditClick = async (e) => {
setIsEmailEdit(true);
};
const onUsernameEditClick = async (e) => {
setIsUsernameEdit(true);
};
const onCollegeEditClick = async (e) => {
setIsCollegeEdit(true);
};
const onMajorEditClick = async (e) => {
setIsMajorEdit(true);
};
const onEditClick = (e) => {
const { id } = e.target
setIsEdit((prev) => ({...prev, [id] : true })
};

이런식으로요!


const onCancelClick = async (e) => {
setFormData(content);
};

return (
<>
{formData && (
<form className="form" onSubmit={onSubmit}>
<div className="flex w-full gap-x-5">
<input
type="text"
placeholder="Add Tags.."
id="email"
value={formData.user.email}
className="input grow"
onChange={handleChange}
/>
Comment on lines +55 to +63
Copy link

Choose a reason for hiding this comment

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

이 부분도 isEdit이 true면 input이지만, isEdit이 false면 그냥 텍스트로 보여지도록 설정해야 할 것 같습니다!

<>
{isEmailEdit ? (
<div>
<button className="small-button w-16">submit</button>
<button className="small-button w-16" onClick={onCancelClick}>cancel</button>
</div>
) : (
<button className="small-button w-16" onClick={onEmailEditClick}>edit</button>
)}
</>
</div>
<div className="flex w-full gap-x-5">
<input
type="text"
placeholder="Add Tags.."
id="username"
value={formData.user.username}
className="input grow"
onChange={handleChange}
/>
<>
{isUsernameEdit ? (
<div>
<button className="small-button w-16">submit</button>
<button className="small-button w-16" onClick={onCancelClick}>cancel</button>
</div>
) : (
<button className="small-button w-16" onClick={onUsernameEditClick}>edit</button>
)}
</>
</div>
<div className="flex w-full gap-x-5">
<input
type="text"
placeholder="Add Tags.."
id="college"
value={formData.college}
className="input grow"
onChange={handleChange}
/>
<>
{isCollegeEdit ? (
<div>
<button className="small-button w-16">submit</button>
<button className="small-button w-16" onClick={onCancelClick}>cancel</button>
</div>
) : (
<button className="small-button w-16" onClick={onCollegeEditClick}>edit</button>
)}
</>
</div>
<div className="flex w-full gap-x-5">
<input
type="text"
placeholder="Add Tags.."
id="major"
value={formData.major}
className="input grow"
onChange={handleChange}
/>
<>
{isMajorEdit ? (
<div>
<button className="small-button w-16">submit</button>
<button className="small-button w-16" onClick={onCancelClick}>cancel</button>
</div>
) : (
<button className="small-button w-16" onClick={onMajorEditClick}>edit</button>
)}
</>
</div>
</form>
)}
</>
);
};
15 changes: 13 additions & 2 deletions src/components/Header/index.jsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,27 @@
import { useEffect, useState } from "react";
import { useEffect, useState, } from "react";
import lion from "../../assets/images/lion.jpeg";
import { Link } from "react-router-dom";
import { Link, useParams } from "react-router-dom";
import { getCookie, removeCookie } from "../../utils/cookie";


const Header = () => {
const [isUser, setIsUser] = useState("");


useEffect(() => {
const user = getCookie("access_token") ? true : false;
setIsUser(user);
}, []);



const handleLogout = () => {
removeCookie("access_token");
window.location.href = "/"; // 새로고침 - 로그아웃 되었다는 것을 인지시켜주기 위해
};



return (
<div
id="header-wrapper"
Expand All @@ -38,6 +46,9 @@ const Header = () => {
</>
) : (
<>
<Link to="/mypage" className="mr-10 p-3 uppercase">
mypage
</Link>
<Link to="/" onClick={handleLogout} className="mr-10 p-3 uppercase">
log out
</Link>
Expand Down
54 changes: 54 additions & 0 deletions src/routes/MyPage.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { useEffect, useState } from "react";
import { useNavigate, useParams } from "react-router-dom";
import { SmallPost } from "../components/Posts";
import { MyPageInput } from "../components/EditInput";

import { Link } from "react-router-dom";
import { getPosts, getUser, getMyPage } from "../apis/api";
import { getCookie } from "../utils/cookie";

const MyPage = () => {
const [userProfile, setUserProfile] = useState();

const [tags, setTags] = useState([]);
const [searchTags, setSearchTags] = useState([]);
const [searchValue, setSearchValue] = useState("");
const [postList, setPostList] = useState([]);

useEffect(() => {
// access_token이 있으면 유저 정보 가져옴
if (getCookie("access_token")) {
const getMyPageAPI = async () => {
const userProfile = await getMyPage();
setUserProfile(userProfile);
Copy link

Choose a reason for hiding this comment

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

userProfile을 받아올 때 아마 major, college, user 이렇게 나눠져 있고, user 안에 username과 email이 있을 거예요. 굳이 이 상태로 쓸 필요는 없겠죠?
저라면 필요한 값들만 넣어줄 것 같습니다.

Suggested change
setUserProfile(userProfile);
setUserProfile({
email : userProfile.user.email,
username : userProfile.user.username,
major : userProfile.major,
college : userProfile.college,
});

이런 식으로요!

그리고 userProfile 변수가 중복 사용된 것 같은데, 아마 문제는 없었을 것 같은데 그래도 최대한 변수명은 다르게 설정해주는게 좋아요!

};
const getPostsAPI = async () => {
const posts = await getPosts();
setPostList(posts);
};
getPostsAPI();
getMyPageAPI();
}
}, []);

return (
<div>
{userProfile && (//userProfile을 안 받아왔을 때에 대한 처리.
<>
<MyPageInput content={userProfile}></MyPageInput>
</>
)}
<div className="w-full flex-row">
{postList.filter((post) =>
post.author.id === userProfile.user.id
)
.map((post) => (
<SmallPost key={post.id} post={post} />
))
}
</div>
</div>
);
};

export default MyPage;
Loading