Skip to content

Commit 419db83

Browse files
committed
Merge branch 'dev-frontend' of https://github.com/boostcamp-2020/Project18-C-Bootion into feat/106
2 parents a835072 + 4678d6d commit 419db83

File tree

18 files changed

+284
-352
lines changed

18 files changed

+284
-352
lines changed
+1-1
Loading

frontend/src/assets/toggle-down.svg

+1-1
Loading

frontend/src/components/atoms/BlockContent/BlockContent.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ const isGridOrColumn = (block: Block): boolean =>
2020

2121
const blockContentCSS = css`
2222
display: flex;
23-
align-items: center;
23+
align-items: stretch;
2424
`;
2525
const editableDivCSS = (block: Block): SerializedStyles => css`
2626
margin: 5;

frontend/src/components/atoms/HeaderButton/HeaderButton.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,13 @@ const buttonCss = (): SerializedStyles => css`
1919
}
2020
`;
2121

22-
function HeaderButton({ children, handleClick }: any): JSX.Element {
22+
function HeaderButton({ children, clickHandler }: any): JSX.Element {
2323
return (
2424
<div
2525
role="button"
2626
css={buttonCss()}
27-
onClick={handleClick}
28-
onKeyUp={handleClick}
27+
onClick={clickHandler}
28+
onKeyUp={clickHandler}
2929
tabIndex={0}
3030
>
3131
{children}

frontend/src/components/molecules/BlockComponent/BlockComponent.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import { useRecoilState, useRecoilValue } from 'recoil';
1616
const isGridOrColumn = (block: Block): boolean =>
1717
block.type === BlockType.GRID || block.type === BlockType.COLUMN;
1818

19-
const blockCss = (): SerializedStyles => css`
19+
const blockCss = css`
2020
width: 100%;
2121
max-width: 1000px;
2222
margin-top: 3px;
@@ -41,7 +41,7 @@ function BlockComponent({ blockDTO }: { blockDTO: Block }): JSX.Element {
4141
const blockRef: any = blockRefState[blockDTO.id];
4242

4343
return (
44-
<div css={blockCss()}>
44+
<div css={blockCss}>
4545
<div
4646
css={{ position: 'relative' }}
4747
onMouseEnter={() => setHoverId(blockDTO.id)}

frontend/src/components/molecules/Editor/Editor.tsx

+16-5
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33
import { jsx, css } from '@emotion/react';
44

55
import { BlockComponent } from '@components/molecules';
6-
import { useRecoilValue } from 'recoil';
6+
import { useRecoilState, useRecoilValue } from 'recoil';
77
import { pageState, blockMapState } from '@/stores';
8+
import { Suspense, useEffect } from 'react';
9+
import { readBlockMap } from '@/utils';
810

911
const wrapperCss = () => css`
1012
padding-left: calc(96px + env(safe-area-inset-left));
@@ -16,13 +18,22 @@ const wrapperCss = () => css`
1618

1719
function Editor(): JSX.Element {
1820
const page = useRecoilValue(pageState);
19-
const blockMap = useRecoilValue(blockMapState);
21+
// const blockMap = useRecoilValue(blockMapState);
22+
const [blockMap, setBlockMap] = useRecoilState(blockMapState);
23+
24+
useEffect(() => {
25+
(async () => {
26+
setBlockMap((await readBlockMap(page.id)).blockMap);
27+
})();
28+
}, [page, setBlockMap]);
2029

2130
return (
2231
<div css={wrapperCss()}>
23-
{blockMap[page.rootId].childIdList.map((blockId: string) => (
24-
<BlockComponent key={blockId} blockDTO={blockMap[blockId]} />
25-
))}
32+
<Suspense fallback={<div>로딩 중...</div>}>
33+
{blockMap[page.rootId].childIdList.map((blockId: string) => (
34+
<BlockComponent key={blockId} blockDTO={blockMap[blockId]} />
35+
))}
36+
</Suspense>
2637
</div>
2738
);
2839
}

frontend/src/components/molecules/Header/Header.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { ReactComponent as Dots } from '@assets/dots.svg';
66
import { ReactComponent as Check } from '@assets/check.svg';
77
import { HeaderLink, HeaderButton } from '@components/atoms';
88
import { useRecoilValue } from 'recoil';
9-
import { selectedPageState, staticMenuToggleState } from '@/stores';
9+
import { pageState, staticMenuToggleState } from '@/stores';
1010

1111
const headerCss = () => css`
1212
width: 100%;
@@ -38,7 +38,7 @@ interface Props {}
3838

3939
function Header({}: Props): JSX.Element {
4040
const staticMenuToggle = useRecoilValue(staticMenuToggleState);
41-
const selectedPage = useRecoilValue(selectedPageState);
41+
const selectedPage = useRecoilValue(pageState);
4242

4343
return (
4444
<div css={headerCss()}>

frontend/src/components/molecules/Menu/Menu.tsx

+21-21
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,13 @@ import { Suspense } from 'react';
55
import { useRecoilState, useSetRecoilState } from 'recoil';
66

77
import {
8+
blockMapState,
89
hoveredMenuToggleState,
910
pagesState,
10-
selectedPageState,
11+
pageState,
1112
staticMenuToggleState,
1213
} from '@/stores';
13-
import { createPage } from '@/utils';
14+
import { createPage, readBlockMap } from '@/utils';
1415
import { HeaderButton } from '@atoms/index';
1516
import { ReactComponent as DoubleChevronLeft } from '@assets/doubleChevronLeft.svg';
1617
import { ReactComponent as PlusPage } from '@assets/plusPage.svg';
@@ -42,37 +43,36 @@ const buttonsCss = () => css`
4243
line-height: 1.2;
4344
font-size: 14px;
4445
flex-grow: 0;
45-
margin-right: 8px;
46+
margin-right: 14px;
4647
min-width: 0;
4748
`;
48-
const plusCss = () => css`
49-
margin-right: 5px;
49+
const plusCss = (staticMenuToggle: boolean) => css`
50+
margin-right: ${staticMenuToggle ? 5 : 0}px;
5051
border: 1px solid rgba(55, 53, 47, 0.16);
5152
border-radius: 3px;
5253
`;
5354

54-
interface Props {}
55-
56-
function Menu({}: Props): JSX.Element {
55+
function Menu(): JSX.Element {
5756
const [pages, setPages] = useRecoilState(pagesState);
58-
const setSelectedPage = useSetRecoilState(selectedPageState);
57+
const setSelectedPage = useSetRecoilState(pageState);
5958
const [staticMenuToggle, setStaticMenuToggle] = useRecoilState(
6059
staticMenuToggleState,
6160
);
6261
const [hoveredMenuToggle, setHoveredMenuToggle] = useRecoilState(
6362
hoveredMenuToggleState,
6463
);
64+
const setBlockMap = useSetRecoilState(blockMapState);
6565

66-
const handleCreatingPage = () => {
67-
const doFetch = async () => {
68-
const { pages: updated, page: created } = await createPage();
69-
setPages(updated);
70-
setSelectedPage(created);
71-
};
72-
doFetch();
66+
const CreatingPageHandler = async () => {
67+
const { pages: updated, page: created } = await createPage();
68+
const { blockMap } = await readBlockMap(created.id);
69+
console.log({ blockMap });
70+
setBlockMap(blockMap);
71+
setPages(updated);
72+
setSelectedPage(created);
7373
};
7474

75-
const handleClickClose = () => {
75+
const clickCloseHandler = () => {
7676
setStaticMenuToggle(false);
7777
setHoveredMenuToggle(false);
7878
};
@@ -81,13 +81,13 @@ function Menu({}: Props): JSX.Element {
8181
<div css={wrapperCss(staticMenuToggle)}>
8282
{hoveredMenuToggle && (
8383
<div css={buttonsCss()}>
84-
<div css={plusCss()}>
85-
<HeaderButton handleClick={handleCreatingPage}>
84+
<div css={plusCss(staticMenuToggle)}>
85+
<HeaderButton clickHandler={CreatingPageHandler}>
8686
<PlusPage />
8787
</HeaderButton>
8888
</div>
8989
{staticMenuToggle && (
90-
<HeaderButton handleClick={handleClickClose}>
90+
<HeaderButton clickHandler={clickCloseHandler}>
9191
<DoubleChevronLeft />
9292
</HeaderButton>
9393
)}
@@ -96,7 +96,7 @@ function Menu({}: Props): JSX.Element {
9696
<div css={workspaceCss()}>WORKSPACE</div>
9797
<Suspense fallback={<div>Loading...</div>}>
9898
{pages.map((page) => (
99-
<MenuItem page={page} />
99+
<MenuItem key={page.id} page={page} />
100100
))}
101101
</Suspense>
102102
</div>

frontend/src/components/molecules/MenuItem/MenuItem.tsx

+44-19
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,33 @@
11
/** @jsx jsx */
22
/** @jsxRuntime classic */
33
import { css, jsx } from '@emotion/react';
4-
import { useRecoilState } from 'recoil';
4+
import { useRecoilState, useSetRecoilState } from 'recoil';
55
import { useState } from 'react';
66

77
import { Page } from '@/schemes';
8-
import { selectedPageState } from '@/stores';
8+
import { blockMapState, pagesState, pageState } from '@/stores';
99
import { HeaderButton } from '@atoms/index';
1010
import { ReactComponent as Trash } from '@assets/trash.svg';
11+
import { deletePage, readBlockMap, refreshPages } from '@/utils';
1112

12-
const itemCss = (isHovered: boolean) => css`
13+
const itemWrapperCss = () => css`
14+
position: relative;
1315
align-items: center;
16+
cursor: pointer;
17+
`;
18+
const itemCss = (isHovered: boolean) => css`
1419
min-height: 27px;
1520
padding: 2px 14px;
1621
padding-right: ${isHovered ? 8 : 14}px;
17-
cursor: pointer;
1822
background: ${isHovered ? 'rgba(55, 53, 47, 0.08)' : 'inherit'};
1923
`;
2024
const selectedItemCss = (isHovered: boolean) => css`
21-
align-items: center;
2225
min-height: 27px;
2326
padding: 2px 14px;
2427
padding-right: ${isHovered ? 8 : 14}px;
2528
background: ${isHovered
2629
? 'rgba(55, 53, 47, 0.16)'
2730
: 'rgba(55, 53, 47, 0.08)'};
28-
cursor: pointer;
2931
`;
3032
const titleCss = () => css`
3133
color: rgb(55, 53, 47);
@@ -37,40 +39,63 @@ const titleCss = () => css`
3739
text-overflow: ellipsis;
3840
`;
3941
const trashCss = () => css`
40-
float: right;
42+
position: absolute;
43+
top: 2px;
44+
right: 13px;
4145
`;
4246

4347
interface Props {
4448
page: Page;
4549
}
4650

4751
function MenuItem({ page }: Props): JSX.Element {
48-
const [selectedPage, setSelectedPage] = useRecoilState(selectedPageState);
52+
const [selectedPage, setSelectedPage] = useRecoilState(pageState);
4953
const [hoverToggle, setHoverToggle] = useState(false);
54+
const setPages = useSetRecoilState(pagesState);
55+
const setBlockMap = useSetRecoilState(blockMapState);
56+
57+
const selectPageHandler = async () => {
58+
setBlockMap((await readBlockMap(page.id)).blockMap);
59+
setSelectedPage(page);
60+
};
61+
62+
const deletePageHandler = async () => {
63+
await deletePage(page.id);
64+
const pages = await refreshPages();
5065

51-
const handleDeletePage = () => {};
66+
if (page.id === selectedPage.id) {
67+
const nextSelectedPage = pages[0];
68+
setBlockMap((await readBlockMap(nextSelectedPage.id)).blockMap);
69+
setSelectedPage(nextSelectedPage);
70+
}
71+
setPages(pages);
72+
};
5273

5374
return (
5475
<div
55-
key={page.id}
56-
css={
57-
selectedPage.id === page.id
58-
? selectedItemCss(hoverToggle)
59-
: itemCss(hoverToggle)
60-
}
61-
onClick={() => setSelectedPage(page)}
62-
onKeyUp={() => setSelectedPage(page)}
76+
css={itemWrapperCss()}
6377
onMouseEnter={() => setHoverToggle(true)}
6478
onMouseLeave={() => setHoverToggle(false)}
6579
>
80+
<div
81+
key={page.id}
82+
css={
83+
selectedPage.id === page.id
84+
? selectedItemCss(hoverToggle)
85+
: itemCss(hoverToggle)
86+
}
87+
onClick={selectPageHandler}
88+
onKeyUp={selectPageHandler}
89+
>
90+
<div css={titleCss()}>{page.title || 'Untitled'}</div>
91+
</div>
6692
{hoverToggle && (
6793
<div css={trashCss()}>
68-
<HeaderButton handleClick={handleDeletePage}>
94+
<HeaderButton clickHandler={deletePageHandler}>
6995
<Trash />
7096
</HeaderButton>
7197
</div>
7298
)}
73-
<div css={titleCss()}>{page.title || 'Untitled'}</div>
7499
</div>
75100
);
76101
}

frontend/src/components/molecules/Title/Title.tsx

+9-6
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
import { jsx, css } from '@emotion/react';
44

55
import { useRecoilState, useSetRecoilState } from 'recoil';
6-
import { pagesState, selectedPageState } from '@/stores';
6+
import { pagesState, pageState } from '@/stores';
77
import { ChangeEvent, useEffect, useRef } from 'react';
8-
import { debounce, readPages, updatePage } from '@/utils';
8+
import { debounce, refreshPages, updatePage } from '@/utils';
99
import { Page } from '@/schemes';
1010

1111
const wrapperCss = () => css`
@@ -48,15 +48,18 @@ const titleCss = () => css`
4848
`;
4949

5050
function Title(): JSX.Element {
51-
const [selectedPage, setSelectedPage] = useRecoilState(selectedPageState);
51+
const [selectedPage, setSelectedPage] = useRecoilState(pageState);
5252
const setPages = useSetRecoilState(pagesState);
5353
const caretRef = useRef(0);
5454
const updateSelectedPage = useRef(
55-
debounce(async (updatedPage: Page) => {
55+
debounce(async (page: Page) => {
5656
caretRef.current = window.getSelection().focusOffset;
5757

58-
setSelectedPage(await updatePage(updatedPage));
59-
setPages(await readPages());
58+
const { page: updatedPage } = await updatePage(page);
59+
const updatedPages = await refreshPages();
60+
61+
setSelectedPage(updatedPage);
62+
setPages(updatedPages);
6063
}, 300),
6164
).current;
6265

frontend/src/components/organisms/HeaderMenu/HeaderMenu.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ function HeaderMenu(): JSX.Element {
5151
onMouseEnter={() => setHoveredMenuToggle(true)}
5252
onMouseLeave={() => setHoveredMenuToggle(false)}
5353
>
54-
<HeaderButton handleClick={() => setStaticMenuToggle(!staticMenuToggle)}>
54+
<HeaderButton clickHandler={() => setStaticMenuToggle(!staticMenuToggle)}>
5555
{staticMenuToggle ||
5656
(!hoveredMenuToggle ? <HamburgerMenu /> : <DoubleChevronRight />)}
5757
</HeaderButton>

0 commit comments

Comments
 (0)