diff --git a/src/App.tsx b/src/App.tsx
index 11b1bc0f..8e295566 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -8,10 +8,10 @@ import { useQueryErrorResetBoundary } from '@tanstack/react-query';
import ErrorBoundary from '@/common/component/ErrorBoundary/ErrorBoundary';
import { HTTPError } from '@/shared/api/HTTPError';
-import GlobalDrawer from '@/shared/component/GlobalDrawer/GlobalDrawer';
import Header from '@/shared/component/Header/Header';
import ModalContainer from '@/shared/component/Modal/ModalContainer';
import SideNavBar from '@/shared/component/SideNavBar/SideNavBar';
+import TimeBlockDrawer from '@/shared/component/TimeBlockDrawer/TimeBlockDrawer';
import { HTTP_STATUS_CODE } from '@/shared/constant/api';
import { PATH } from '@/shared/constant/path';
import ErrorPage from '@/shared/page/errorPage/ErrorPage';
@@ -54,7 +54,7 @@ const App = () => {
-
+
);
diff --git a/src/common/asset/svg/ic_close.svg b/src/common/asset/svg/ic_close.svg
new file mode 100644
index 00000000..52e3a0b6
--- /dev/null
+++ b/src/common/asset/svg/ic_close.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/common/asset/svg/ic_cloud_upload.svg b/src/common/asset/svg/ic_cloud_upload.svg
new file mode 100644
index 00000000..85751022
--- /dev/null
+++ b/src/common/asset/svg/ic_cloud_upload.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/common/asset/svg/ic_group.svg b/src/common/asset/svg/ic_group.svg
new file mode 100644
index 00000000..749a7340
--- /dev/null
+++ b/src/common/asset/svg/ic_group.svg
@@ -0,0 +1,5 @@
+
diff --git a/src/common/asset/svg/ic_note_black.svg b/src/common/asset/svg/ic_note_black.svg
new file mode 100644
index 00000000..7a5f639a
--- /dev/null
+++ b/src/common/asset/svg/ic_note_black.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/common/asset/svg/ic_paper.svg b/src/common/asset/svg/ic_paper.svg
new file mode 100644
index 00000000..d61abf28
--- /dev/null
+++ b/src/common/asset/svg/ic_paper.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/common/asset/svg/ic_subdirectory_arrow_right.svg b/src/common/asset/svg/ic_subdirectory_arrow_right.svg
new file mode 100644
index 00000000..056aea43
--- /dev/null
+++ b/src/common/asset/svg/ic_subdirectory_arrow_right.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/common/component/Button/Button.style.ts b/src/common/component/Button/Button.style.ts
index 9109be35..e070c503 100644
--- a/src/common/component/Button/Button.style.ts
+++ b/src/common/component/Button/Button.style.ts
@@ -22,6 +22,8 @@ export const buttonStyle = css({
'&:disabled:not(:focus)': {
backgroundColor: theme.colors.gray_100,
color: theme.colors.gray_500,
+
+ cursor: 'default',
},
transition: 'all .2s ease-in',
@@ -53,6 +55,14 @@ export const variantStyle = (variant: Required['variant']) => {
backgroundColor: theme.colors.gray_200,
},
}),
+ fourth: css({
+ color: theme.colors.gray_800,
+ backgroundColor: theme.colors.white,
+
+ '&:hover': {
+ backgroundColor: theme.colors.gray_100,
+ },
+ }),
outline: css({
color: theme.colors.gray_800,
backgroundColor: theme.colors.white,
diff --git a/src/common/component/Button/Button.tsx b/src/common/component/Button/Button.tsx
index a6876c13..c49e7468 100644
--- a/src/common/component/Button/Button.tsx
+++ b/src/common/component/Button/Button.tsx
@@ -5,7 +5,7 @@ import { Size } from '@/common/type/design';
import { buttonStyle, sizeStyle, variantStyle } from './Button.style';
export interface ButtonProps extends ButtonHTMLAttributes {
- variant?: 'primary' | 'secondary' | 'tertiary' | 'outline' | 'text';
+ variant?: 'primary' | 'secondary' | 'tertiary' | 'fourth' | 'outline' | 'text';
size?: Extract;
}
diff --git a/src/common/component/CommandButton/CommandButton.style.ts b/src/common/component/CommandButton/CommandButton.style.ts
index dc855d4c..92003608 100644
--- a/src/common/component/CommandButton/CommandButton.style.ts
+++ b/src/common/component/CommandButton/CommandButton.style.ts
@@ -40,7 +40,10 @@ export const commonStyle = css({
});
export const keyStyle = (
- variant: Extract<'primary' | 'tertiary' | 'outline', Omit['variant']>
+ variant: Extract<
+ 'primary' | 'tertiary' | 'fourth' | 'outline',
+ Omit['variant']
+ >
) => {
const style = {
primary: css({
@@ -59,6 +62,14 @@ export const keyStyle = (
color: theme.colors.gray_500,
},
}),
+ fourth: css({
+ backgroundColor: theme.colors.gray_100,
+
+ '&:disabled:not(:focus)': {
+ backgroundColor: theme.colors.gray_100,
+ color: theme.colors.gray_500,
+ },
+ }),
outline: css({
backgroundColor: theme.colors.gray_100,
@@ -92,6 +103,12 @@ export const sizeStyle = (size: Required['size']) => {
small: css({
padding: '0.7rem 1rem 0.7rem 1.4rem',
+ ...theme.text.body08,
+ }),
+ /** Button_24 */
+ xSmall: css({
+ padding: '0.6rem 1rem',
+
...theme.text.body08,
}),
};
diff --git a/src/common/component/CommandButton/CommandButton.tsx b/src/common/component/CommandButton/CommandButton.tsx
index b7311913..a57344f7 100644
--- a/src/common/component/CommandButton/CommandButton.tsx
+++ b/src/common/component/CommandButton/CommandButton.tsx
@@ -12,8 +12,8 @@ import {
} from '@/common/component/CommandButton/CommandButton.style';
export interface CommandButtonProps extends ButtonProps {
- variant?: Extract;
- size?: Extract;
+ variant?: Extract;
+ size?: Extract;
commandKey: string;
isCommand?: boolean;
isFrontIcon?: boolean;
diff --git a/src/page/archiving/index/ArchivingPage.tsx b/src/page/archiving/index/ArchivingPage.tsx
index 3218d060..b0f4901e 100644
--- a/src/page/archiving/index/ArchivingPage.tsx
+++ b/src/page/archiving/index/ArchivingPage.tsx
@@ -34,8 +34,12 @@ const ArchivingPage = () => {
/** TODO: 추후 block id에 따른 API 응답으로 데이터 넣기 */
openDrawer({
title: selectedBlockFromDashboard.name,
- startDate: '2024-09-13',
- endDate: '2024-09-24',
+ startDate: new Date('2024-09-13'),
+ endDate: new Date('2024-09-24'),
+ blockType: 'MEETING',
+ color: '#FFE6E8',
+ taggedMembers: [],
+ handoverNotes: [],
files: [],
});
}
diff --git a/src/page/archiving/index/component/TimeBlockBar/BlockInfo/BlockInfo.style.ts b/src/page/archiving/index/component/TimeBlockBar/BlockInfo/BlockInfo.style.ts
new file mode 100644
index 00000000..962604c7
--- /dev/null
+++ b/src/page/archiving/index/component/TimeBlockBar/BlockInfo/BlockInfo.style.ts
@@ -0,0 +1,11 @@
+import { css } from '@emotion/react';
+
+import { theme } from '@/common/style/theme/theme';
+
+export const periodStyle = css({
+ color: theme.colors.gray_800,
+});
+
+export const titleInputStyle = css({
+ width: '21.4rem',
+});
diff --git a/src/page/archiving/index/component/TimeBlockBar/BlockInfo/BlockInfo.tsx b/src/page/archiving/index/component/TimeBlockBar/BlockInfo/BlockInfo.tsx
new file mode 100644
index 00000000..8280dbf5
--- /dev/null
+++ b/src/page/archiving/index/component/TimeBlockBar/BlockInfo/BlockInfo.tsx
@@ -0,0 +1,33 @@
+import DatePicker from '@/common/component/DatePicker';
+import Flex from '@/common/component/Flex/Flex';
+import Heading from '@/common/component/Heading/Heading';
+import Input from '@/common/component/Input/Input';
+import Text from '@/common/component/Text/Text';
+
+import { periodStyle, titleInputStyle } from '@/page/archiving/index/component/TimeBlockBar/BlockInfo/BlockInfo.style';
+import { formattingDate } from '@/page/archiving/index/util/date';
+
+interface BlockInfoProps {
+ title: string;
+ startDate: Date;
+ endDate: Date;
+ isEditable: boolean;
+}
+
+const BlockInfo = ({ title, startDate, endDate, isEditable }: BlockInfoProps) => {
+ return (
+
+ {isEditable ? : {title}}
+
+ {isEditable ? (
+
+ ) : (
+
+ {formattingDate(startDate)} ~ {formattingDate(endDate)}
+
+ )}
+
+ );
+};
+
+export default BlockInfo;
diff --git a/src/page/archiving/index/component/TimeBlockBar/TaggedNotes/TaggedNoteItem/TaggedNoteItem.style.ts b/src/page/archiving/index/component/TimeBlockBar/TaggedNotes/TaggedNoteItem/TaggedNoteItem.style.ts
new file mode 100644
index 00000000..163bd544
--- /dev/null
+++ b/src/page/archiving/index/component/TimeBlockBar/TaggedNotes/TaggedNoteItem/TaggedNoteItem.style.ts
@@ -0,0 +1,11 @@
+import { css } from '@emotion/react';
+
+export const handoverNoteItemStyle = css({
+ display: 'block',
+
+ maxWidth: '20.6rem',
+
+ whiteSpace: 'nowrap',
+ overflow: 'hidden',
+ textOverflow: 'ellipsis',
+});
diff --git a/src/page/archiving/index/component/TimeBlockBar/TaggedNotes/TaggedNoteItem/TaggedNoteItem.tsx b/src/page/archiving/index/component/TimeBlockBar/TaggedNotes/TaggedNoteItem/TaggedNoteItem.tsx
new file mode 100644
index 00000000..34548bc6
--- /dev/null
+++ b/src/page/archiving/index/component/TimeBlockBar/TaggedNotes/TaggedNoteItem/TaggedNoteItem.tsx
@@ -0,0 +1,23 @@
+import IcArrowRight from '@/common/asset/svg/ic_subdirectory_arrow_right.svg?react';
+import Button from '@/common/component/Button/Button';
+import Flex from '@/common/component/Flex/Flex';
+
+import { handoverNoteItemStyle } from '@/page/archiving/index/component/TimeBlockBar/TaggedNotes/TaggedNoteItem/TaggedNoteItem.style';
+
+interface TaggedNoteItemProps {
+ title: string;
+ isEditable: boolean;
+}
+
+const TaggedNoteItem = ({ title, isEditable }: TaggedNoteItemProps) => {
+ return (
+
+
+
+
+ );
+};
+
+export default TaggedNoteItem;
diff --git a/src/page/archiving/index/component/TimeBlockBar/TaggedNotes/TaggedNotes.tsx b/src/page/archiving/index/component/TimeBlockBar/TaggedNotes/TaggedNotes.tsx
new file mode 100644
index 00000000..be917a1a
--- /dev/null
+++ b/src/page/archiving/index/component/TimeBlockBar/TaggedNotes/TaggedNotes.tsx
@@ -0,0 +1,37 @@
+import IcNote from '@/common/asset/svg/ic_note_black.svg?react';
+import Flex from '@/common/component/Flex/Flex';
+import Text from '@/common/component/Text/Text';
+
+import TaggedNoteItem from '@/page/archiving/index/component/TimeBlockBar/TaggedNotes/TaggedNoteItem/TaggedNoteItem';
+import { listHeaderStyle } from '@/page/archiving/index/component/TimeBlockBar/TimeBlockBar.style';
+
+interface TaggedNotesProps {
+ isEditable: boolean;
+}
+
+// TODO: API 추가
+const HANDOVER_NOTE_LIST = [
+ { id: 1, title: '세상에서 제일 긴 제목을 지을거에요 나는 하하하하하하하ㅏ핳하' },
+ { id: 2, title: 'OT 인수인계' },
+ { id: 3, title: '엄마 나는 토스에 가고 싶어요' },
+];
+
+const TaggedNotes = ({ isEditable }: TaggedNotesProps) => {
+ return (
+
+
+
+
+ 태그된 인수인계 노트
+
+
+
+ {HANDOVER_NOTE_LIST.map((data) => (
+
+ ))}
+
+
+ );
+};
+
+export default TaggedNotes;
diff --git a/src/page/archiving/index/component/TimeBlockBar/TimeBlockBar.style.ts b/src/page/archiving/index/component/TimeBlockBar/TimeBlockBar.style.ts
new file mode 100644
index 00000000..c31beeb7
--- /dev/null
+++ b/src/page/archiving/index/component/TimeBlockBar/TimeBlockBar.style.ts
@@ -0,0 +1,27 @@
+import { css } from '@emotion/react';
+
+import { theme } from '@/common/style/theme/theme';
+
+export const closeBtnStyle = css({
+ position: 'absolute',
+
+ right: '2.2rem',
+ top: '3.2rem',
+
+ cursor: 'pointer',
+});
+
+export const circleStyle = (color: string) =>
+ css({
+ alignItems: 'center',
+ justifyContent: 'center',
+
+ padding: '0.6rem',
+
+ borderRadius: '18px',
+ backgroundColor: color,
+ });
+
+export const listHeaderStyle = css({
+ color: theme.colors.gray_800,
+});
diff --git a/src/page/archiving/index/component/TimeBlockBar/TimeBlockBar.tsx b/src/page/archiving/index/component/TimeBlockBar/TimeBlockBar.tsx
new file mode 100644
index 00000000..452d239e
--- /dev/null
+++ b/src/page/archiving/index/component/TimeBlockBar/TimeBlockBar.tsx
@@ -0,0 +1,56 @@
+import { useState } from 'react';
+
+import CloseButton from '@/common/asset/svg/ic_close.svg?react';
+import CommandButton from '@/common/component/CommandButton/CommandButton';
+import Flex from '@/common/component/Flex/Flex';
+
+import BlockInfo from '@/page/archiving/index/component/TimeBlockBar/BlockInfo/BlockInfo';
+import TaggedNotes from '@/page/archiving/index/component/TimeBlockBar/TaggedNotes/TaggedNotes';
+import { circleStyle, closeBtnStyle } from '@/page/archiving/index/component/TimeBlockBar/TimeBlockBar.style';
+import UploadedFiles from '@/page/archiving/index/component/TimeBlockBar/UploadedFiles/UploadedFiles';
+import { BLOCK_ICON } from '@/page/archiving/index/constant/icon';
+
+import { DrawerContent } from '@/shared/store/drawer';
+
+interface TimeBlockBarProps {
+ content: DrawerContent;
+ onCloseDrawer: () => void;
+}
+
+const TimeBlockBar = ({ content, onCloseDrawer }: TimeBlockBarProps) => {
+ const [isEditable, setIsEditable] = useState(false);
+
+ const handleEditClick = () => {
+ setIsEditable((prevState) => !prevState);
+ };
+
+ return (
+ content && (
+
+
+
+
+
+ {BLOCK_ICON.find((icon) => icon.name === content.blockType)?.icon(content.color)}
+
+
+ {isEditable ? '저장' : '수정하기'}
+
+
+
+
+
+
+
+
+
+ )
+ );
+};
+
+export default TimeBlockBar;
diff --git a/src/page/archiving/index/component/TimeBlockBar/UploadedFiles/FileItem/FileItem.style.ts b/src/page/archiving/index/component/TimeBlockBar/UploadedFiles/FileItem/FileItem.style.ts
new file mode 100644
index 00000000..be85e05f
--- /dev/null
+++ b/src/page/archiving/index/component/TimeBlockBar/UploadedFiles/FileItem/FileItem.style.ts
@@ -0,0 +1,47 @@
+import { css } from '@emotion/react';
+
+import { theme } from '@/common/style/theme/theme';
+
+export const containerStyle = css({
+ gap: '1.2rem',
+ alignItems: 'center',
+ justifyContent: 'space-between',
+
+ width: '100%',
+ padding: '0.6rem',
+
+ backgroundColor: theme.colors.gray_100,
+ borderRadius: '8px',
+
+ cursor: 'pointer',
+
+ '&:hover': {
+ backgroundColor: theme.colors.gray_200,
+ },
+});
+
+export const circleStyle = css({
+ justifyContent: 'center',
+ alignItems: 'center',
+
+ padding: '0.8rem',
+
+ backgroundColor: theme.colors.white,
+ borderRadius: '16px',
+});
+
+export const fileTitleStyle = css({
+ maxWidth: '15rem',
+
+ whiteSpace: 'nowrap',
+ overflow: 'hidden',
+ textOverflow: 'ellipsis',
+});
+
+export const fileCapacityStyle = css({
+ color: theme.colors.gray_800,
+});
+
+export const closeBtnStyle = css({
+ cursor: 'pointer',
+});
diff --git a/src/page/archiving/index/component/TimeBlockBar/UploadedFiles/FileItem/FileItem.tsx b/src/page/archiving/index/component/TimeBlockBar/UploadedFiles/FileItem/FileItem.tsx
new file mode 100644
index 00000000..20d570c9
--- /dev/null
+++ b/src/page/archiving/index/component/TimeBlockBar/UploadedFiles/FileItem/FileItem.tsx
@@ -0,0 +1,42 @@
+import CloseButton from '@/common/asset/svg/ic_close.svg?react';
+import IcPDF from '@/common/asset/svg/ic_pdf_file.svg?react';
+import Flex from '@/common/component/Flex/Flex';
+import Text from '@/common/component/Text/Text';
+
+import {
+ circleStyle,
+ closeBtnStyle,
+ containerStyle,
+ fileCapacityStyle,
+ fileTitleStyle,
+} from '@/page/archiving/index/component/TimeBlockBar/UploadedFiles/FileItem/FileItem.style';
+
+interface FileItemProps {
+ title: string;
+ capacity: string;
+ isEditable: boolean;
+}
+
+const FileItem = ({ title, capacity, isEditable }: FileItemProps) => {
+ return (
+
+
+
+
+
+
+
+ {title}
+
+
+ {capacity}
+
+
+
+
+ {isEditable && }
+
+ );
+};
+
+export default FileItem;
diff --git a/src/page/archiving/index/component/TimeBlockBar/UploadedFiles/UploadedFiles.tsx b/src/page/archiving/index/component/TimeBlockBar/UploadedFiles/UploadedFiles.tsx
new file mode 100644
index 00000000..2103196d
--- /dev/null
+++ b/src/page/archiving/index/component/TimeBlockBar/UploadedFiles/UploadedFiles.tsx
@@ -0,0 +1,45 @@
+import IcCloudUpload from '@/common/asset/svg/ic_cloud_upload.svg?react';
+import IcPaper from '@/common/asset/svg/ic_paper.svg?react';
+import Button from '@/common/component/Button/Button';
+import Flex from '@/common/component/Flex/Flex';
+import Text from '@/common/component/Text/Text';
+
+import { listHeaderStyle } from '@/page/archiving/index/component/TimeBlockBar/TimeBlockBar.style';
+import FileItem from '@/page/archiving/index/component/TimeBlockBar/UploadedFiles/FileItem/FileItem';
+
+interface UploadedFileProps {
+ isEditable: boolean;
+}
+
+// TODO: API 추가
+const UPLOADED_FILE_LIST = [
+ { id: 1, title: '세상에서 제일 긴 제목을 지을거에요 나는', capacity: '2.4 MB' },
+ { id: 2, title: 'OT 인수인계', capacity: '2.9 MB' },
+ { id: 3, title: '엄마 나는 토스에 가고 싶어요', capacity: '10.7 MB' },
+];
+
+const UploadedFile = ({ isEditable }: UploadedFileProps) => {
+ return (
+
+
+
+
+ 업로드된 파일
+
+
+ {isEditable && (
+
+ )}
+
+ {UPLOADED_FILE_LIST.map((data) => (
+
+ ))}
+
+
+ );
+};
+
+export default UploadedFile;
diff --git a/src/page/archiving/index/hook/common/useInteractTimeline.ts b/src/page/archiving/index/hook/common/useInteractTimeline.ts
index 59e20ac2..13500494 100644
--- a/src/page/archiving/index/hook/common/useInteractTimeline.ts
+++ b/src/page/archiving/index/hook/common/useInteractTimeline.ts
@@ -21,8 +21,12 @@ export const useInteractTimeline = () => {
/** TODO: 추후 block id에 따른 API 응답으로 데이터 넣기 */
openDrawer({
title: 'OT 준비',
- startDate: '2024-09-13',
- endDate: '2024-09-24',
+ startDate: new Date('2024.09.13'),
+ endDate: new Date('2024.09.15'),
+ blockType: 'MEETING',
+ color: '#FFE6E8',
+ taggedMembers: [],
+ handoverNotes: [],
files: [],
});
};
diff --git a/src/shared/component/GlobalDrawer/GlobalDrawer.style.ts b/src/shared/component/TimeBlockDrawer/TimeBlockDrawer.style.ts
similarity index 82%
rename from src/shared/component/GlobalDrawer/GlobalDrawer.style.ts
rename to src/shared/component/TimeBlockDrawer/TimeBlockDrawer.style.ts
index a4247f9e..fb4cbd3c 100644
--- a/src/shared/component/GlobalDrawer/GlobalDrawer.style.ts
+++ b/src/shared/component/TimeBlockDrawer/TimeBlockDrawer.style.ts
@@ -4,17 +4,18 @@ import { theme } from '@/common/style/theme/theme';
export const containerStyle = (isOpen: boolean) =>
css({
+ flexShrink: 0,
position: 'sticky',
right: 0,
-
zIndex: theme.zIndex.overlayMiddle,
width: isOpen ? '27rem' : 0,
height: 'calc(100vh)',
+ padding: '0 1.6rem',
overflow: 'hidden',
- borderRadius: '16px',
+ borderLeft: `1px solid ${theme.colors.gray_300}`,
boxShadow: '0px 2px 10px 0px rgba(0, 0, 0, 0.10)',
backgroundColor: theme.colors.white,
diff --git a/src/shared/component/GlobalDrawer/GlobalDrawer.tsx b/src/shared/component/TimeBlockDrawer/TimeBlockDrawer.tsx
similarity index 63%
rename from src/shared/component/GlobalDrawer/GlobalDrawer.tsx
rename to src/shared/component/TimeBlockDrawer/TimeBlockDrawer.tsx
index 6cad31ce..877d0d1b 100644
--- a/src/shared/component/GlobalDrawer/GlobalDrawer.tsx
+++ b/src/shared/component/TimeBlockDrawer/TimeBlockDrawer.tsx
@@ -1,14 +1,15 @@
import { useEffect } from 'react';
import { useLocation } from 'react-router-dom';
-import Heading from '@/common/component/Heading/Heading';
import { useOutsideClick } from '@/common/hook';
-import { containerStyle } from '@/shared/component/GlobalDrawer/GlobalDrawer.style';
+import TimeBlockBar from '@/page/archiving/index/component/TimeBlockBar/TimeBlockBar';
+
+import { containerStyle } from '@/shared/component/TimeBlockDrawer/TimeBlockDrawer.style';
import { PATH } from '@/shared/constant/path';
import { useDrawerAction, useDrawerContent, useDrawerIsOpen } from '@/shared/store/drawer';
-const GlobalDrawer = () => {
+const TimeBlockDrawer = () => {
const isOpen = useDrawerIsOpen();
const { closeDrawer } = useDrawerAction();
const content = useDrawerContent();
@@ -25,13 +26,12 @@ const GlobalDrawer = () => {
}, [isOpen, closeDrawer, pathname]);
return (
-
+ content && (
+
+ )
);
};
-export default GlobalDrawer;
+export default TimeBlockDrawer;
diff --git a/src/shared/store/drawer.ts b/src/shared/store/drawer.ts
index 3edf9810..6ce877d9 100644
--- a/src/shared/store/drawer.ts
+++ b/src/shared/store/drawer.ts
@@ -2,10 +2,14 @@ import { create } from 'zustand';
import { File } from '@/shared/type/file';
-type DrawerContent = {
+export type DrawerContent = {
title: string;
- startDate: string;
- endDate: string;
+ startDate: Date;
+ endDate: Date;
+ blockType: string;
+ color: string;
+ taggedMembers: [];
+ handoverNotes: [];
files: File[];
} | null;