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

my room 메모 CRUD 기능 #117

Merged
merged 22 commits into from
Aug 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
c942d80
style: 컴포넌트 경로 변경
Bhanjo Jul 24, 2022
7dbd6f6
Merge remote-tracking branch 'origin/develop' into feature/hanjo/view…
Bhanjo Jul 24, 2022
effbae2
feat: 마이룸 데이터 패치 기능 구현
Bhanjo Jul 24, 2022
4506cab
Merge branch 'develop' into feature/hanjo/viewMyRoomData
Bhanjo Jul 26, 2022
4412696
refactor: react query로 데이터 패치 리팩터링
Bhanjo Jul 26, 2022
0b5b477
Merge remote-tracking branch 'origin/develop' into feature/hanjo/view…
Bhanjo Aug 7, 2022
31060a6
style: 폴더명 변경
Bhanjo Aug 7, 2022
18d2107
feat: room 데이터 패치 기능 구현
Bhanjo Aug 8, 2022
e943e4b
feat: 로그인 검증 구현
Bhanjo Aug 11, 2022
27e560c
feat: 메모 등록 기능 구현
Bhanjo Aug 11, 2022
b142b8e
feat: 메모장 전체 보기 기능 구현
Bhanjo Aug 11, 2022
0db626c
Merge remote-tracking branch 'origin/develop' into feature/hanjo/view…
Bhanjo Aug 12, 2022
3a8b081
refactor: api 분리, 리액트 쿼리를 커스텀 훅으로 리팩토링
Bhanjo Aug 12, 2022
8a4cc8d
refactor: 메모 등록 로직 리액트 쿼리로 리팩터링
Bhanjo Aug 12, 2022
042c1ad
fix: 간혈적으로 리패치 안 되는 현상 해결, 메모장 최신순 정렬
Bhanjo Aug 13, 2022
8efa798
style: 변수명 직관적으로 변경, 토스트 메시지 등장 시기 변경
Bhanjo Aug 13, 2022
6b735ed
fix: 일부 메모 내용이 안보이는 현상 해결
Bhanjo Aug 13, 2022
84a680c
setting: await expression 규칙 추가 (겁나 중요)
Bhanjo Aug 13, 2022
ef0ca72
fix: 데이터 리패칭 오류 해결
Bhanjo Aug 13, 2022
732ce46
feat: 메모장 수정 기능 구현
Bhanjo Aug 14, 2022
1a6c203
fix: 에러 처리 로직을 api단으로 이동
Bhanjo Aug 14, 2022
6d89e59
fix: 메모 빈 값 허용 문제 해결
Bhanjo Aug 14, 2022
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
3 changes: 2 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"no-shadow": 0,
"import/no-extraneous-dependencies": ["error", { "devDependencies": true }],
"react/function-component-definition": 0,
"@typescript-eslint/no-non-null-assertion": 0
"@typescript-eslint/no-non-null-assertion": 0,
"require-await": "error"
}
}
4 changes: 1 addition & 3 deletions src/DesignSystem/BackgroundMain/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,7 @@ const BackgroundBox = styled.div`
justify-content: center;
margin: 0 auto;
box-shadow: none;

/* s3에 이미지 업로드 필요 */
background-image: url('image/backgoundNoCloud.png');
background-image: url('../../image/backgoundNoCloud.png');
background-position: center;
background-repeat: no-repeat;
background-size: 1440px 1024px;
Expand Down
67 changes: 67 additions & 0 deletions src/api/memo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import axios from 'axios';
import { NextRouter } from 'next/router';
import Axios from '~lib/axios';

type Form = {
routerId?: string;
id?: number;
title: string;
content: string;
};

export const fetchRoomById = async (id: string, showError: () => void, router: NextRouter) => {
try {
const res = await Axios.get(`/api/rooms/${id}`, { withCredentials: true });
return res.data;
} catch (e) {
if (e instanceof Error) {
if (axios.isAxiosError(e)) {
if (e.response?.status === 401) {
showError();
router.push('/sign-in');
}
}
throw new Error('fetchRoomById Error');
}
}
};

export const fetchAllMemos = async (id: string, showError: () => void) => {
try {
const res = await Axios.get(`/api/rooms/${id}/memos`, { withCredentials: true });
return res.data;
} catch (e) {
if (e instanceof Error) {
showError();
throw new Error('fetchAllMemos Error');
}
}
};

export const registMemo = async (form: Form) => {
try {
await Axios.post(
`/api/rooms/${form.routerId}/memos`,
{ title: form.title, content: form.content },
{ withCredentials: true },
);
} catch (e) {
if (e instanceof Error) {
throw new Error('registMemo Error', e);
}
}
};

export const updateMemo = async (form: Form) => {
try {
await Axios.put(
`/api/memos/${form.id}`,
{ title: form.title, content: form.content },
{ withCredentials: true },
);
} catch (e) {
if (e instanceof Error) {
throw new Error('updateMemo Error', e);
}
}
};
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import styled from 'styled-components';
import Image from 'next/image';

const Avatar = () => {
type Props = {
roomOwner: string;
};

const Avatar = ({ roomOwner }: Props) => {
return (
<AvatarBox>
{/* 사용자 이름 패치 필요 */}
<p>사용자이름</p>
<p>{roomOwner}</p>
<Image src="/image/human.png" alt="아바타" width="312" height="398" />
</AvatarBox>
);
Expand Down
92 changes: 52 additions & 40 deletions src/pages/my-room/Board.tsx → src/components/Rooms/Board.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,54 +9,66 @@ type PostShape = 'circle' | 'rectangle';

type Props = {
handleModalClick: () => void;
handleSecondModalClick: (id: number) => void;
handleMemoModalClick: (id: number) => void;
comments: Array<Comment>;
};

// comments는 최신 5개? 처음 5개? 만약 5개 미만이면?
const Board = ({ handleModalClick, handleSecondModalClick, comments }: Props) => {
const Board = ({ handleModalClick, handleMemoModalClick, comments }: Props) => {
return (
<BoardContainer>
<BoardRack />
<BoardBody>
<MoreButton type="button" onClick={handleModalClick}>
<LionDoll />
</MoreButton>
<Post top="10%" left="8%">
<PostBody shape="circle" onClick={() => handleSecondModalClick(0)}>
<p>{comments && comments[0].title}</p>
</PostBody>
<Tape position="center" />
</Post>
<Post top="10%" left="65%" rotate="right">
<PostBody shape="rectangle" onClick={() => handleSecondModalClick(1)}>
<p>{comments && comments[1].title}</p>
</PostBody>
<Tape fill="#3efff3" opacity="0.52" position="leftTop" />
<Tape fill="#3efff3" opacity="0.52" position="rightBottom" />
</Post>
<Post top="30%" left="35%" rotate="left">
<PostBody shape="rectangle" onClick={() => handleSecondModalClick(2)}>
<p>{comments && comments[2].title}</p>
</PostBody>
<Tape fill="#fff844" opacity="0.63" position="leftTop" />
<Tape fill="#fff844" opacity="0.63" position="rightTop" />
<Tape fill="#fff844" opacity="0.63" position="leftBottom" />
<Tape fill="#fff844" opacity="0.63" position="rightBottom" />
</Post>
<Post top="50%" left="10%" rotate="right">
<PostBody shape="rectangle" onClick={() => handleSecondModalClick(3)}>
<p>{comments && comments[3].title}</p>
</PostBody>
<Tape fill="#caa5E8" opacity="0.52" position="leftTop" />
<Tape fill="#caa5E8" opacity="0.52" position="rightBottom" />
</Post>
<Post top="55%" left="65%">
<PostBody shape="circle" onClick={() => handleSecondModalClick(4)}>
<p>{comments && comments[4].title}</p>
</PostBody>
<Tape fill="#b3ec9f" opacity="0.59" position="center" />
</Post>
<>
<MoreButton type="button" onClick={handleModalClick}>
<LionDoll />
</MoreButton>
{comments[0] && (
<Post top="10%" left="8%">
<PostBody shape="circle" onClick={() => handleMemoModalClick(comments[0].id)}>
<p>{comments && comments[0].title}</p>
</PostBody>
<Tape position="center" />
</Post>
)}
{comments[1] && (
<Post top="10%" left="65%" rotate="right">
<PostBody shape="rectangle" onClick={() => handleMemoModalClick(comments[1].id)}>
<p>{comments && comments[1].title}</p>
</PostBody>
<Tape fill="#3efff3" opacity="0.52" position="leftTop" />
<Tape fill="#3efff3" opacity="0.52" position="rightBottom" />
</Post>
)}
{comments[2] && (
<Post top="30%" left="35%" rotate="left">
<PostBody shape="rectangle" onClick={() => handleMemoModalClick(comments[2].id)}>
<p>{comments && comments[2].title}</p>
</PostBody>
<Tape fill="#fff844" opacity="0.63" position="leftTop" />
<Tape fill="#fff844" opacity="0.63" position="rightTop" />
<Tape fill="#fff844" opacity="0.63" position="leftBottom" />
<Tape fill="#fff844" opacity="0.63" position="rightBottom" />
</Post>
)}
{comments[3] && (
<Post top="50%" left="10%" rotate="right">
<PostBody shape="rectangle" onClick={() => handleMemoModalClick(comments[3].id)}>
<p>{comments && comments[3].title}</p>
</PostBody>
<Tape fill="#caa5E8" opacity="0.52" position="leftTop" />
<Tape fill="#caa5E8" opacity="0.52" position="rightBottom" />
</Post>
)}
{comments[4] && (
<Post top="55%" left="65%">
<PostBody shape="circle" onClick={() => handleMemoModalClick(comments[4].id)}>
<p>{comments && comments[4].title}</p>
</PostBody>
<Tape fill="#b3ec9f" opacity="0.59" position="center" />
</Post>
)}
</>
</BoardBody>
</BoardContainer>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,44 +13,38 @@ import useModalOutsideClick from '~/hooks/useModalOutsideClick';

type Props = {
onClose: () => void;
handleSecondModalClick: (id: number | null) => void;
handleMemoModalClick: (id: number | null) => void;
comments: Array<Comment>;
};

const GuestBook = ({ onClose, handleSecondModalClick, comments }: Props) => {
const GuestBook = ({ onClose, handleMemoModalClick, comments }: Props) => {
// 모달창 크기에 최대 메모장 10개 보임 => 즉, 10개당 1슬라이드를 의미 나머지 발생 시 + 1
const slideRef = useRef<HTMLDivElement>(null);
const slideTotal = useRef<number>(Math.ceil(comments?.length / 10) - 1);

const [currentSlide, setCurrentSlide] = useState<number>(0);

// prev 클릭 시 현재 슬라이드를 -1, next 클릭은 +1, 각각 처음 혹은 끝이면 반대 방향으로 이동
const onClickPrev = () => {
const onClickNext = () => {
if (currentSlide === 0) {
setCurrentSlide(slideTotal.current);
} else {
setCurrentSlide(currentSlide - 1);
}
};

const onClickNext = () => {
const onClickPrev = () => {
if (currentSlide >= slideTotal.current) {
setCurrentSlide(0);
} else {
setCurrentSlide(currentSlide + 1);
}
};

// DOM 직접 제어 방식
// useEffect(() => {
// if (slideRef.current !== null) {
// slideRef.current.style.transform = `translateX(-${currentSlide}00%)`;
// }
// }, [currentSlide]);

useEffect(() => {
if (slideRef.current !== null) {
scrollTo(slideRef.current, { left: currentSlide * 920, behavior: 'smooth' });
// wrap-reverse로 인해 스크롤 반전
scrollTo(slideRef.current, { left: currentSlide * -960, behavior: 'smooth' });
}
}, [currentSlide]);

Expand Down Expand Up @@ -79,19 +73,19 @@ const GuestBook = ({ onClose, handleSecondModalClick, comments }: Props) => {
</InputGroup>
<MemoButtonWrap>
<Button size="small">삭제</Button>
<Button size="small" onClick={() => handleSecondModalClick(null)}>
<Button size="small" onClick={() => handleMemoModalClick(null)}>
+추가
</Button>
</MemoButtonWrap>
</MidBox>

<CommentWrap ref={slideRef}>
{comments?.map((memo: { id: number; title: string; nickname: string }) => (
{comments?.map((memo: { id: number; title: string }) => (
<MemoBox key={memo.id}>
<Tape fill="#62fade" opacity="0.7" />
<button type="button" onClick={() => handleSecondModalClick(memo.id)}>
<button type="button" onClick={() => handleMemoModalClick(memo.id)}>
<p>{memo.title}</p>
<p>{memo.nickname}</p>
{/* <p>{memo.nickname}</p> */}
</button>
</MemoBox>
))}
Expand Down Expand Up @@ -173,7 +167,7 @@ const MemoButtonWrap = styled.div`

const CommentWrap = styled.div`
display: flex;
flex-flow: column wrap;
flex-flow: column wrap-reverse;
gap: 30px 50px;
justify-content: center;
transition: 0.3s ease-out;
Expand Down
Loading