Skip to content

Commit

Permalink
[Feature/BAR-231] 저장하는 페이지 UI 구현 (#64)
Browse files Browse the repository at this point in the history
* style(Card): 줄바꿈 적용

* feat: Spinner 컴포넌트 구현

* fix: bookmark -> archive 이름 통일

* refactor(_app): 빈 태그 제거

* refactor: 공통 MenuButton(MenuDropdown) 컴포넌트 적용

* feat: archive api 정의

* refactor(Tab): 마크업 및 스타일 수정

* feat: 저장하는 페이지 UI 구현

* style(NotFoundArchiveCard): 레이아웃 수정

* feat(ArchiveCardTabContent): 복사, 저장 횟수 추가

* refactor(ArchiveCardTabContent): ArchivedCard 컴포넌트 분리

* refactor(domain/저장하는): 저장하는 페이지 내 Tab 컴포넌트명 수정

* refactor: MenuButton -> MenuDropdown 컴포넌트명 수정

* feat(domain/저장하는): 수정 기능 구현

* refactor: useEditArchives -> useUpdateArchives hook 이름 수정

* style(ArchivedCard): 수정 완료 버튼 스타일 추가

* feat(domain/저장하는): 삭제 기능 구현

* refactor(domain/저장하는): null 반환 제거
  • Loading branch information
dmswl98 authored Feb 16, 2024
1 parent f87e8fd commit fb93660
Show file tree
Hide file tree
Showing 41 changed files with 769 additions and 130 deletions.
12 changes: 5 additions & 7 deletions pages/_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,11 @@ import Toast from '@components/Toast';

const App = ({ Component, pageProps }: AppProps) => {
return (
<>
<TanstackQueryProvider dehydratedState={pageProps.dehydratedState}>
<Component {...pageProps} />
<Toast />
<Modal />
</TanstackQueryProvider>
</>
<TanstackQueryProvider dehydratedState={pageProps.dehydratedState}>
<Component {...pageProps} />
<Toast />
<Modal />
</TanstackQueryProvider>
);
};

Expand Down
12 changes: 12 additions & 0 deletions pages/archive/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import Layout from '@components/Layout';
import Archive from '@domain/저장하는/components/Archive';

const Page = () => {
return (
<Layout>
<Archive />
</Layout>
);
};

export default Page;
18 changes: 18 additions & 0 deletions src/assets/images/empty.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 3 additions & 6 deletions src/components/Card/Card.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,9 @@ import { COLORS } from '@styles/tokens';

import Card from '.';

const CARD_CONTENT = `
안녕하세요. 리더님!
어제 줌 회의로 가볍게 인사드렸는데
메신저로는 처음 인사 드립니다 :)
다름이 아니라 업무 진행을 위해 JIRA
권한을 받고자 하는데 시간 괜찮으실 때 권한 추가해주실 수 있을까요?
const CARD_CONTENT = `안녕하세요. 리더님!
어제 줌 회의로 가볍게 인사드렸는데 메신저로는 처음 인사 드립니다 :)
다름이 아니라 업무 진행을 위해 JIRA 권한을 받고자 하는데 시간 괜찮으실 때 권한 추가해주실 수 있을까요?
`;

const CARD_COUNT_STYLE = {
Expand Down
2 changes: 2 additions & 0 deletions src/components/Card/style.css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export const menu = style({
top: '16px',
right: '16px',
padding: '8px',
zIndex: 10,
});

export const header = style([
Expand All @@ -69,6 +70,7 @@ export const body = style([
{
whiteSpace: 'pre-wrap',
wordBreak: 'keep-all',
whiteSpace: 'pre-line',
},
]);

Expand Down
9 changes: 9 additions & 0 deletions src/components/Column/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { type PropsWithChildren } from 'react';

import * as styles from './style.css';

const Column = ({ children }: PropsWithChildren) => {
return <ol className={styles.container}>{children}</ol>;
};

export default Column;
8 changes: 8 additions & 0 deletions src/components/Column/style.css.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { style } from '@vanilla-extract/css';

export const container = style({
display: 'flex',
flexDirection: 'column',
gap: '16px',
flex: '1',
});
25 changes: 25 additions & 0 deletions src/components/Dropdown/MenuDropdown/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import Icon from '@components/Icon';
import { COLORS } from '@styles/tokens';

import Dropdown from '..';

interface MenuDropdownProps {
onEdit?: () => void;
onDelete?: () => void;
}

const MenuDropdown = ({ onEdit, onDelete }: MenuDropdownProps) => {
return (
<Dropdown size="small" placement="bottom-right">
<Dropdown.Trigger>
<Icon icon="menu" color={COLORS['Grey/300']} />
</Dropdown.Trigger>
<Dropdown.List>
{onEdit && <Dropdown.Item onClick={onEdit}>수정하기</Dropdown.Item>}
{onDelete && <Dropdown.Item onClick={onDelete}>삭제하기</Dropdown.Item>}
</Dropdown.List>
</Dropdown>
);
};

export default MenuDropdown;
2 changes: 1 addition & 1 deletion src/components/Layout/components/UserButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import ProfileButton from './ProfileButton';
const UserButton = () => {
return (
<div className={styles.userButton}>
<Link href={ROUTES.BOOKMARK} className={styles.bookmark}>
<Link href={ROUTES.ARCHIVE} className={styles.archive}>
<Icon icon="bookmark" color={COLORS['Grey/400']} />
</Link>
<ProfileButton />
Expand Down
2 changes: 1 addition & 1 deletion src/components/Layout/style.css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export const buttonsWrapper = recipe({
},
});

export const bookmark = style({
export const archive = style({
display: 'inline-block',
padding: '12px',
});
Expand Down
11 changes: 11 additions & 0 deletions src/components/Loading/Spinner/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import * as styles from './style.css';

const Spinner = () => {
return (
<div className={styles.wrapper}>
<div className={styles.spinner} />
</div>
);
};

export default Spinner;
22 changes: 22 additions & 0 deletions src/components/Loading/Spinner/style.css.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { keyframes, style } from '@vanilla-extract/css';

import { COLORS } from '@styles/tokens';

const spin = keyframes({
to: { transform: 'rotate(360deg)' },
});

export const wrapper = style({
width: 'fit-content',
margin: '0 auto',
});

export const spinner = style({
display: 'inline-block',
width: '38px',
height: '38px',
border: `5px solid ${COLORS['Grey/100']}`,
borderRadius: '50%',
borderTopColor: COLORS['Blue/Default'],
animation: `${spin} 1s ease-in-out infinite`,
});
22 changes: 18 additions & 4 deletions src/components/Tabs/components/TabsContent.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,32 @@
import type { PropsWithChildren } from 'react';
import type { HTMLAttributes, PropsWithChildren } from 'react';
import clsx from 'clsx';

import { useTabsContext } from '..';
import * as styles from '../style.css';

export interface TabsContentProps {
export interface TabsContentProps extends HTMLAttributes<HTMLElement> {
value: string;
}

const TabsContent = ({
children,
value,
...props
}: PropsWithChildren<TabsContentProps>) => {
const { selectedTab } = useTabsContext();
const { type, selectedTab } = useTabsContext();

return <>{selectedTab === value ? children : null}</>;
return (
<>
{selectedTab === value ? (
<section
{...props}
className={clsx(styles.tabContent({ type }), props.className)}
>
{children}
</section>
) : null}
</>
);
};

export default TabsContent;
3 changes: 2 additions & 1 deletion src/components/Tabs/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { createContext, type PropsWithChildren, useContext } from 'react';
import TabsContent from './components/TabsContent';
import TabsList from './components/TabsList';
import TabsTrigger from './components/TabsTrigger';
import * as styles from './style.css';

type TabsType = 'filter' | 'switcher';

Expand Down Expand Up @@ -30,7 +31,7 @@ const TabsRoot = ({
<TabsContext.Provider
value={{ type, selectedTab, onSelectTab: handleTabSelect }}
>
{children}
<div className={styles.tab}>{children}</div>
</TabsContext.Provider>
);
};
Expand Down
20 changes: 19 additions & 1 deletion src/components/Tabs/style.css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,18 @@ import { recipe } from '@vanilla-extract/recipes';
import { COLORS } from '@styles/tokens';
import * as utils from '@styles/utils.css';

export const tab = style({
width: '100%',
});

export const tabsList = recipe({
base: [utils.flexCenter],
base: {
display: 'flex',
},
variants: {
type: {
switcher: {
justifyContent: 'center',
borderRadius: '100px',
backgroundColor: COLORS['Grey/200'],
},
Expand Down Expand Up @@ -66,6 +73,17 @@ export const tabsTrigger = recipe({
},
});

export const tabContent = recipe({
variants: {
type: {
switcher: {},
filter: {
marginTop: '24px',
},
},
},
});

export const isActiveSwitcher = style({
fontWeight: 700,
color: COLORS['Blue/Dark'],
Expand Down
2 changes: 1 addition & 1 deletion src/constants/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@ export const CATEGORY_COLOR = {
위로하기: 'purple',
'감사 전하기': 'red',
'안부 전하기': 'yellow',
기타: 'black',
기타: 'grey',
} as const;
2 changes: 1 addition & 1 deletion src/constants/routes.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export const ROUTES = {
LANDING: '/',
MAIN: '/main',
BOOKMARK: '/bookmark',
ARCHIVE: '/archive',
PRIVACY: '/terms/privacy',
USE: '/terms/use',
} as const;
30 changes: 5 additions & 25 deletions src/domain/끄적이는/components/Card/History/index.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
import dayjs from 'dayjs';

import MenuDropdown from '@components/Dropdown/MenuDropdown';
import Icon from '@components/Icon';
import useDeleteTemporalMemo from '@domain/끄적이는/mutations/useDeleteTemporalMemo';
import useEditTemporalMemo from '@domain/끄적이는/mutations/useEditTemporalMemo';
import { type TemporalMemo } from '@domain/끄적이는/types';
import { useInput } from '@hooks/useInput';
import useModal from '@hooks/useModal';
import { useToastStore } from '@stores/toast';
import { COLORS } from '@styles/tokens';

import EditInput from '../../EditInput';
import SettingDialog from '../components/SettingDialog';
import * as styles from './style.css';

interface WriteHistoryCardProps extends TemporalMemo {
Expand All @@ -35,12 +34,6 @@ const WriteHistoryCard = ({
defaultValue: content,
});

const {
isOpen: settingModalOpen,
handleOpen: showSettingModal,
handleClose: hideSettingModal,
} = useModal();

const handleCopyClick = () => {
navigator.clipboard.writeText(content);
showToast({
Expand Down Expand Up @@ -96,26 +89,13 @@ const WriteHistoryCard = ({
className={styles.icon}
/>
</button>
<button
onClick={settingModalOpen ? hideSettingModal : showSettingModal}
>
<Icon
icon="menu"
color={COLORS['Grey/300']}
className={styles.icon}
/>
</button>
<MenuDropdown
onEdit={onEditClick}
onDelete={() => deleteTemporalMemo(id)}
/>
</div>
</div>

<p className={styles.value}>{content}</p>

{settingModalOpen && (
<SettingDialog
onEditClick={onEditClick}
onDeleteClick={() => deleteTemporalMemo(id)}
/>
)}
</li>
);
};
Expand Down
Loading

0 comments on commit fb93660

Please sign in to comment.