Skip to content
This repository has been archived by the owner on Jul 29, 2024. It is now read-only.

[FE] feat: 휴지통 기능 구현 #281

Merged
merged 26 commits into from
Aug 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
ffafa7a
test: trash api handler 추가
jeonjeunghoon Aug 11, 2023
6948d35
feat: `trash` api 요청 로직 구현
jeonjeunghoon Aug 11, 2023
f603160
feat: 휴지통 컴포넌트 구현
jeonjeunghoon Aug 11, 2023
942b09f
feat: `TrashCanPage` 페이지 추가
jeonjeunghoon Aug 14, 2023
e9a753b
feat: `TrashCan` 과 `TrashCanPage` 연결
jeonjeunghoon Aug 14, 2023
86ca2dd
feat: `Layout` 에 휴지통 연결
jeonjeunghoon Aug 14, 2023
1f994bd
Merge branch 'develop' of https://github.com/woowacourse-teams/2023-d…
jeonjeunghoon Aug 14, 2023
dbb259d
feat: TrashCanTable 추가
jeonjeunghoon Aug 15, 2023
77caf99
Merge branch 'develop' of https://github.com/woowacourse-teams/2023-d…
jeonjeunghoon Aug 15, 2023
7a6d687
feat: 휴지통 페이지 router에 연결
jeonjeunghoon Aug 15, 2023
58e4ce3
test: 휴지통 mocking 데이터 추가
jeonjeunghoon Aug 15, 2023
fb009f3
fix: 체크 박스 버그 수정
jeonjeunghoon Aug 15, 2023
4f4f689
feat: useDeletedPermanentWritings 추가
jeonjeunghoon Aug 15, 2023
d721455
feat: useRestoreDeletedWritings 추가
jeonjeunghoon Aug 15, 2023
8493ea5
feat: `useTrashCanTable` 훅 구현
jeonjeunghoon Aug 15, 2023
a050fb1
feat: `TrashCanTable` 에 훅 추가
jeonjeunghoon Aug 15, 2023
d0aa74d
test: mocking data 수정
jeonjeunghoon Aug 15, 2023
2a7f07d
feat: `useDeletedWritings` 훅 구현
jeonjeunghoon Aug 15, 2023
6919c18
feat: `DeletedWritingList` 컴포넌트 구현
jeonjeunghoon Aug 15, 2023
6bf8c35
feat: 체크된 글이 없을 때 글 삭제/복구 로직 방어
jeonjeunghoon Aug 15, 2023
5a13f9a
fix: 잘못된 메시지 수정
jeonjeunghoon Aug 16, 2023
b332b1e
Merge branch 'develop' of https://github.com/woowacourse-teams/2023-d…
jeonjeunghoon Aug 16, 2023
fd09c6b
design: 카테고리, 휴지통 스타일 수정
jeonjeunghoon Aug 16, 2023
e32e7eb
Merge branch 'develop' of https://github.com/woowacourse-teams/2023-d…
jeonjeunghoon Aug 16, 2023
bcb8ae0
design: WritingList 스타일 수정
jeonjeunghoon Aug 16, 2023
c8b0d66
chore: backend reverse commit 생성
echo724 Aug 16, 2023
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
12 changes: 10 additions & 2 deletions frontend/src/apis/trash.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { trashURL } from 'constants/apis/url';
import { http } from './fetch';
import { GetDeletedWritingsResponse } from 'types/apis/trash';

// 글 휴지통으로 이동: POST
export const moveToTrash = (writingIds: number[]) =>
http.post(`${trashURL}`, {
http.post(trashURL, {
json: {
writingIds,
isPermanentDelete: false,
Expand All @@ -12,9 +13,16 @@ export const moveToTrash = (writingIds: number[]) =>

// 글 영구 삭제: POST
export const deletePermanentWritings = (writingIds: number[]) =>
http.post(`${trashURL}`, {
http.post(trashURL, {
json: {
writingIds,
isPermanentDelete: true,
},
});

// 휴지통에 있는 글 목록 조회: GET
export const getDeletedWritings = (): Promise<GetDeletedWritingsResponse> => http.get(trashURL);

// 휴지통에서 글 복구: POST
export const restoreDeletedWritings = (writingIds: number[]) =>
http.post(`${trashURL}/restore`, { json: { writingIds } });
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,5 @@ const S = {
display: flex;
flex-direction: column;
width: 100%;
padding-left: 2rem;
`,
};
6 changes: 6 additions & 0 deletions frontend/src/components/@common/Accordion/AccordionTitle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,15 @@ export default AccordionTitle;
const S = {
Container: styled.div`
display: flex;
gap: 0.8rem;
align-items: center;
width: 100%;
padding: 0 0.4rem;
border-radius: 4px;

&:hover {
background-color: ${({ theme }) => theme.color.gray4};
}
`,

IconButton: styled.button<Record<'$isOpen', boolean>>`
Expand Down
14 changes: 8 additions & 6 deletions frontend/src/components/Category/Category/Category.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { TrashCanIcon, PencilIcon } from 'assets/icons';
import { PencilIcon } from 'assets/icons';
import { usePageNavigate } from 'hooks/usePageNavigate';
import { KeyboardEventHandler } from 'react';
import { styled } from 'styled-components';
Expand Down Expand Up @@ -95,22 +95,22 @@ const S = {
justify-content: space-between;
align-items: center;
width: 100%;
height: 3.2rem;
padding: 0.8rem;
border-radius: 8px;
height: 3.6rem;
border-radius: 4px;
font-size: 1.4rem;

&:hover {
div {
display: inline-flex;
gap: 0.8rem;
gap: 0.4rem;
}
}
`,

CategoryButton: styled.button`
flex: 1;
min-width: 0;
height: 100%;
text-align: left;
`,

Expand All @@ -136,6 +136,7 @@ const S = {

IconContainer: styled.div`
display: none;
margin-right: 0.4rem;
`,

Button: styled.button`
Expand All @@ -144,7 +145,8 @@ const S = {
align-items: center;
width: 2rem;
height: 2.4rem;
border-radius: 8px;
padding: 0.4rem;
border-radius: 4px;

&:hover {
background-color: ${({ theme }) => theme.color.gray5};
Expand Down
12 changes: 6 additions & 6 deletions frontend/src/components/Category/Header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import useCategoryInput from '../useCategoryInput';
import { useCategoryMutation } from '../useCategoryMutation';
import { isValidCategoryName } from '../isValidCategoryName';
import Input from 'components/@common/Input/Input';
import { PlusCircleIcon } from 'assets/icons';
import { PlusIcon } from 'assets/icons';

const Header = () => {
const {
Expand Down Expand Up @@ -50,7 +50,7 @@ const Header = () => {
/>
) : (
<S.Button onClick={openInput} aria-label='카테고리 추가 입력 창 열기'>
<PlusCircleIcon width={12} height={12} />
<PlusIcon width={12} height={12} />
</S.Button>
)}
</S.Header>
Expand All @@ -64,10 +64,10 @@ const S = {
display: flex;
justify-content: space-between;
align-items: center;
height: 2.8rem;
height: 3.6rem;
padding: 0.8rem;
font-size: 1.2rem;
font-weight: 400;
padding-right: 0.8rem;
`,

Title: styled.h1`
Expand All @@ -80,8 +80,8 @@ const S = {
justify-content: center;
align-items: center;
width: 2rem;
height: 2.4rem;
border-radius: 8px;
height: 2rem;
border-radius: 4px;

&:hover {
background-color: ${({ theme }) => theme.color.gray5};
Expand Down
27 changes: 13 additions & 14 deletions frontend/src/components/Category/WritingList/WritingList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,8 @@ const WritingList = ({ categoryId, isOpen }: Props) => {
return (
<ul>
{writings.map((writing) => (
<S.Item key={writing.id}>
<S.Item key={writing.id} $isClicked={writingId === writing.id}>
<S.Button
$isClicked={writingId === writing.id}
aria-label={`${writing.title}글 메인화면에 열기`}
onClick={() => goWritingPage({ categoryId, writingId: writing.id })}
>
Expand All @@ -45,33 +44,33 @@ const WritingList = ({ categoryId, isOpen }: Props) => {
export default WritingList;

const S = {
Item: styled.li`
Item: styled.li<{ $isClicked: boolean }>`
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
border-radius: 8px;
height: 3.6rem;
border-radius: 4px;
background-color: ${({ theme, $isClicked }) => $isClicked && theme.color.gray4};

&:hover {
background-color: ${({ theme }) => theme.color.gray5};
background-color: ${({ theme }) => theme.color.gray4};

div {
display: inline-flex;
display: flex;
flex-shrink: 0;
gap: 0.8rem;
}
}
`,

Button: styled.button<{ $isClicked: boolean }>`
Button: styled.button`
display: flex;
align-items: center;
gap: 0.8rem;
gap: 0.4rem;
min-width: 0;
height: 3.6rem;
padding: 0.8rem;
border-radius: 8px;
background-color: ${({ theme, $isClicked }) => $isClicked && theme.color.gray5};
height: 100%;
padding: 0.4rem 0 0.4rem 3.2rem;
border-radius: 4px;
`,

IconWrapper: styled.div`
Expand All @@ -88,7 +87,7 @@ const S = {
`,

NoWritingsText: styled.p`
padding: 0.8rem;
padding: 0.4rem 0 0.4rem 3.2rem;
color: ${({ theme }) => theme.color.gray6};
font-size: 1.4rem;
font-weight: 500;
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/components/DeleteButton/DeleteButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ const S = {
align-items: center;
width: 2rem;
height: 2.4rem;
border-radius: 8px;
border-radius: 4px;

&:hover {
background-color: ${({ theme }) => theme.color.gray6};
background-color: ${({ theme }) => theme.color.gray5};
}
`,
};
100 changes: 100 additions & 0 deletions frontend/src/components/TrashCan/DeletedWritingList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import { WritingIcon } from 'assets/icons';
import { usePageNavigate } from 'hooks/usePageNavigate';
import { useParams } from 'react-router-dom';
import { styled } from 'styled-components';
import DeleteButton from 'components/DeleteButton/DeleteButton';
import { useDeletedWritings } from 'hooks/useDeletedWritings';
import { useDeletePermanentWritings } from 'components/TrashCanTable/useDeletePermanentWritings';

const DeletedWritingList = () => {
const { deletedWritings } = useDeletedWritings();
const { goWritingPage } = usePageNavigate();
const writingId = Number(useParams()['writingId']);
const deletePermanentWritings = useDeletePermanentWritings();

if (!deletedWritings || deletedWritings?.length === 0)
return <S.NoWritingsText>빈 휴지통</S.NoWritingsText>;

return (
<ul>
{deletedWritings.map((deletedWriting) => (
<S.Item key={deletedWriting.id} $isClicked={writingId === deletedWriting.id}>
<S.Button
aria-label={`${deletedWriting.title}글 메인화면에 열기`}
onClick={() =>
goWritingPage({ categoryId: deletedWriting.categoryId, writingId: deletedWriting.id })
}
>
<S.IconWrapper>
<WritingIcon width={14} height={14} />
</S.IconWrapper>
<S.Text>{deletedWriting.title}</S.Text>
</S.Button>
<S.DeleteButtonWrapper>
<DeleteButton onClick={() => deletePermanentWritings([writingId])} />
</S.DeleteButtonWrapper>
</S.Item>
))}
</ul>
);
};

export default DeletedWritingList;

const S = {
Item: styled.li<{ $isClicked: boolean }>`
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
height: 3.6rem;
border-radius: 4px;
background-color: ${({ theme, $isClicked }) => $isClicked && theme.color.gray4};

&:hover {
background-color: ${({ theme }) => theme.color.gray4};

div {
display: inline-flex;
flex-shrink: 0;
gap: 0.8rem;
}
}
`,

Button: styled.button`
display: flex;
align-items: center;
gap: 0.4rem;
min-width: 0;
jeonjeunghoon marked this conversation as resolved.
Show resolved Hide resolved
height: 100%;
padding: 0.4rem 0 0.4rem 3.2rem;
border-radius: 4px;
`,

IconWrapper: styled.div`
flex-shrink: 0;
`,

Text: styled.p`
color: ${({ theme }) => theme.color.gray9};
font-size: 1.4rem;
font-weight: 400;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
`,

NoWritingsText: styled.p`
padding: 0.4rem 0 0.4rem 3.2rem;
color: ${({ theme }) => theme.color.gray6};
font-size: 1.4rem;
font-weight: 500;
cursor: default;
`,

DeleteButtonWrapper: styled.div`
display: none;
margin-right: 0.8rem;
`,
};
60 changes: 60 additions & 0 deletions frontend/src/components/TrashCan/TrashCan.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import Accordion from 'components/@common/Accordion/Accordion';
import { usePageNavigate } from 'hooks/usePageNavigate';
import { styled } from 'styled-components';
import DeletedWritingList from './DeletedWritingList';

const TrashCan = () => {
const { goTrashCanPage } = usePageNavigate();

return (
<Accordion>
<Accordion.Item>
<Accordion.Title>
<S.Button aria-label='휴지통으로 이동하기' onClick={goTrashCanPage}>
<S.Text>휴지통</S.Text>
</S.Button>
</Accordion.Title>
<Accordion.Panel>
<DeletedWritingList />
</Accordion.Panel>
</Accordion.Item>
</Accordion>
);
};

export default TrashCan;

const S = {
Button: styled.button`
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
height: 3.6rem;
border-radius: 8px;
font-size: 1.4rem;

&:hover {
div {
display: inline-flex;
gap: 0.8rem;
}
}
`,

Text: styled.p`
color: ${({ theme }) => theme.color.gray10};
font-weight: 600;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
`,

NoWritingsText: styled.p`
padding: 0.8rem;
color: ${({ theme }) => theme.color.gray6};
font-size: 1.4rem;
font-weight: 500;
cursor: default;
`,
};
Loading
Loading