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

[Refactor] 모달 띄우는 로직, 데이터 상태 로직 리팩토링.. #197

Merged
merged 25 commits into from
Sep 30, 2024
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
23e3d6d
#187 feat: 모달 상태 store
cindy-chaewon Jul 31, 2024
2f33596
#187 fix: 모달 상태 store toggle 추가
cindy-chaewon Jul 31, 2024
1034e74
#187 feat: 모달 zustand로 띄우기
cindy-chaewon Aug 1, 2024
f566a02
#187 fix: 모달 닫힐 때 workspace 클릭 상태 해제
cindy-chaewon Aug 1, 2024
13021a7
#187 fix: 타임블록 생성도 적용 & 오류 해결
cindy-chaewon Aug 1, 2024
52a7280
#187 fix: 사진 미리보기 안되던 오류 해결
cindy-chaewon Aug 1, 2024
73ca6e8
#187 feat: delete 모달에도 적용
cindy-chaewon Aug 1, 2024
77ee9fc
#187 refactor: 필요없는 코드 삭제
cindy-chaewon Aug 1, 2024
5974228
#187 fix: 절대경로 수정
cindy-chaewon Aug 1, 2024
50f68e9
#187 refactor: 워크스페이스, 블록생성
cindy-chaewon Aug 1, 2024
da808c4
#187 fix: 오류 해결
cindy-chaewon Aug 1, 2024
2535167
#187 fix: 불필요한 코드 제거
cindy-chaewon Aug 1, 2024
3a1feff
#187 refactor: 코드리뷰 반영
cindy-chaewon Aug 6, 2024
a741a89
#187 fix: 스토리북 코드 수정
cindy-chaewon Aug 6, 2024
44f9b0c
#187 refactor: 코드리뷰 반영
cindy-chaewon Aug 13, 2024
503f75f
#187 fix: 스토리북 모달 수정
cindy-chaewon Aug 13, 2024
bedbb83
#187 fix: useCallback 제거
cindy-chaewon Aug 13, 2024
f68a155
#187 refactor: 삭제 모달 zustand 로
cindy-chaewon Sep 13, 2024
f825ceb
#187 refactor: 리팩토링
cindy-chaewon Sep 20, 2024
764eacc
#187 refactor: 코드리뷰 반영
cindy-chaewon Sep 29, 2024
404f9a5
#187 fix: 스토리북 파일 에러 해결
cindy-chaewon Sep 30, 2024
aa418e7
#187 fix: svg 네이밍 정리
cindy-chaewon Sep 30, 2024
6ae06bc
#187 fix: 오류 해결
cindy-chaewon Sep 30, 2024
8b41e31
#187 fix : 머지 충돌 해결
cindy-chaewon Sep 30, 2024
fb23c44
#187 fix: 코드리뷰 반영
cindy-chaewon Sep 30, 2024
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
2 changes: 2 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Outlet, useNavigate } from 'react-router-dom';
import { AxiosError } from 'axios';

import ErrorBoundary from '@/common/component/ErrorBoundary/ErrorBoundary';
import ModalContainer from '@/common/component/Modal/ModalContainer';
import { theme } from '@/common/style/theme/theme';

import LeftSidebar from '@/shared/component/LeftSidebar/LeftSidebar';
Expand Down Expand Up @@ -43,6 +44,7 @@ const App = () => {
return (
<ErrorBoundary fallback={ErrorPage} onReset={handleResetError}>
<Login>
<ModalContainer />
<div css={containerStyle}>
<LeftSidebar />
<main css={layoutStyle}>
Expand Down
4 changes: 2 additions & 2 deletions src/common/component/Modal/Modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
/* eslint-disable jsx-a11y/no-noninteractive-element-interactions */

/* eslint-disable jsx-a11y/click-events-have-key-events */
import { ReactElement, useCallback, useEffect } from 'react';
import { ReactNode, useCallback, useEffect } from 'react';
import { createPortal } from 'react-dom';

import { backgroundStyle, dialogStyle } from '@/common/component/Modal/Modal.style';

interface ModalProps {
isOpen: boolean;
children?: ReactElement;
children: ReactNode;
onClose?: () => void;
}

Expand Down
21 changes: 21 additions & 0 deletions src/common/component/Modal/ModalContainer.tsx
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ModalContainer는 사실 블록 생성과 워크스페이스 생성이라는 비즈니스 로직을 담고 있으니까 common/components 에 두는 건 아닌 거 같애 ! shared로 뺍시당

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

넵!!

Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import Modal from '@/common/component/Modal/Modal';

import { BlockProvider } from '@/shared/hook/common/useBlockContext';
import { WorkSpaceProvider } from '@/shared/hook/common/useWorkSpaceContext';
import { useModalStore } from '@/shared/store/modal';

const ModalContainer = () => {
const { isOpen, content, closeModal } = useModalStore();

if (!isOpen || !content) return null;

return (
<Modal isOpen={isOpen} onClose={closeModal}>
<WorkSpaceProvider>
<BlockProvider>{content}</BlockProvider>
</WorkSpaceProvider>
</Modal>
);
};

export default ModalContainer;
43 changes: 22 additions & 21 deletions src/page/archiving/createTimeBlock/component/Block/BlockModal.tsx
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

추가적으로 폴더명이 동사 + 목적어 형태의 문장이 되어버리니까 좀 어색한 느낌이 드는 것 같아요.

createTimeBlock이나 createWorkSpaceModal 둘다 timeBlockModal 형태로 바꾸는 것은 어떤가요 ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

좋습니다! 변경완료 했습니다!

Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import BlockDate from '@/page/archiving/createTimeBlock/component/Block/Date/Blo
import BlockIcon from '@/page/archiving/createTimeBlock/component/Block/Icon/BlockIcon';
import BlockBox from '@/page/archiving/createTimeBlock/component/Box/BlockBox';
import { BLOCK_ICON } from '@/page/archiving/createTimeBlock/constant/iconBlock';
import { BlockData } from '@/page/archiving/createTimeBlock/type/blockType';

import { useState } from 'react';

Expand All @@ -12,35 +11,37 @@ import Flex from '@/common/component/Flex/Flex';
import Input from '@/common/component/Input/Input';
import Text from '@/common/component/Text/Text';

import WorkSapceInfo from '@/shared/component/createWorkSpace/info/WorkSpaceInfo';
import WorkSapceInfo from '@/shared/component/createWorkSpaceModal/info/WorkSpaceInfo';
import { useBlockContext } from '@/shared/hook/common/useBlockContext';

interface BlockModalProps {
onNext: (blockData: BlockData) => void;
}

const BlockModal = ({ onNext }: BlockModalProps) => {
const [blockName, setBlockName] = useState('');
const BlockModal = () => {
const [selectedIcon, setSelectedIcon] = useState<number>(-1);
const [dates, setDates] = useState({ startDate: '', endDate: '' });
const [isDateRangeValid, setIsDateRangeValid] = useState(false);

const { formData, setFormData, nextStep } = useBlockContext();

const handleBlockNameChange = (e: React.ChangeEvent<HTMLInputElement>) => {
if (e.target.value.length <= 25) {
setBlockName(e.target.value);
setFormData({ blockName: e.target.value });
}
};

const isButtonActive =
blockName.trim() !== '' &&
formData.blockName.trim() !== '' &&
selectedIcon !== -1 &&
dates.startDate.length === 10 &&
dates.endDate.length === 10 &&
formData.startDate.length === 10 &&
formData.endDate.length === 10 &&
isDateRangeValid;

const handleNext = () => {
if (isButtonActive) {
const blockType = BLOCK_ICON[selectedIcon].name;
onNext({ blockName, dates, blockType });
const blockIconType = BLOCK_ICON[selectedIcon].name;
setFormData({
blockType: blockIconType,
startDate: formData.startDate,
endDate: formData.endDate,
});
nextStep();
}
};

Expand Down Expand Up @@ -74,22 +75,22 @@ const BlockModal = ({ onNext }: BlockModalProps) => {
size="large"
placeholder="활동,행사명 등"
css={{ width: '100%' }}
value={blockName}
value={formData.blockName}
onChange={handleBlockNameChange}
/>
<Text tag="body7" css={textStyle}>
{blockName.length} / 25
{formData.blockName.length} / 25
</Text>
</Flex>
</BlockBox>

<BlockBox title="기간">
<Flex styles={{ align: 'flex-start', direction: 'column', padding: '0', width: '100%' }}>
<BlockDate
startDate={dates.startDate}
endDate={dates.endDate}
onSetStartDate={(date) => setDates((prev) => ({ ...prev, startDate: date as string }))}
onSetEndDate={(date) => setDates((prev) => ({ ...prev, endDate: date as string }))}
startDate={formData.startDate}
endDate={formData.endDate}
onSetStartDate={(date) => setFormData({ startDate: date })}
onSetEndDate={(date) => setFormData({ endDate: date })}
onSetIsDateRangeValid={setIsDateRangeValid}
/>
</Flex>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,17 @@ import SupportingText from '@/common/component/SupportingText/SupportingText';
interface BlockDateProps {
startDate: string;
endDate: string;
onSetStartDate: (date: string | ((prev: string) => string)) => void;
onSetEndDate: (date: string | ((prev: string) => string)) => void;
onSetStartDate: (date: string) => void;
onSetEndDate: (date: string) => void;
onSetIsDateRangeValid: (isValid: boolean) => void;
}

const BlockDate = ({ startDate, endDate, onSetStartDate, onSetEndDate, onSetIsDateRangeValid }: BlockDateProps) => {
const { dates, validation, handleChange } = useDateRange(
startDate,
endDate,
onSetStartDate,
onSetEndDate,
(date: string) => onSetStartDate(date),
(date: string) => onSetEndDate(date),
onSetIsDateRangeValid
);

Expand Down
31 changes: 16 additions & 15 deletions src/page/archiving/createTimeBlock/component/Upload/UploadModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import BlockItem from '@/page/archiving/createTimeBlock/component/Upload/File/Li
import { flexStyle, scrollStyle } from '@/page/archiving/createTimeBlock/component/Upload/UploadModal.style';
import { useDeleteFileMutation } from '@/page/archiving/createTimeBlock/hook/api/useDeleteFileMutation';
import { usePostTimeBlockMutation } from '@/page/archiving/createTimeBlock/hook/api/usePostTimeBlockMutation';
import { BlockData } from '@/page/archiving/createTimeBlock/type/blockType';
import { formatDatePost } from '@/page/archiving/createTimeBlock/util/date';
import { getRandomColor } from '@/page/archiving/index/util/color';

Expand All @@ -13,23 +12,24 @@ import Button from '@/common/component/Button/Button';
import Flex from '@/common/component/Flex/Flex';

import { Files } from '@/shared/api/time-blocks/team/time-block/type';
import WorkSapceInfo from '@/shared/component/createWorkSpace/info/WorkSpaceInfo';
import WorkSapceInfo from '@/shared/component/createWorkSpaceModal/info/WorkSpaceInfo';
import { useBlockContext } from '@/shared/hook/common/useBlockContext';
import { useModalStore } from '@/shared/store/modal';
import { useTeamStore } from '@/shared/store/team';
import { useToastStore } from '@/shared/store/toast';

interface UploadModalProps {
onClose: () => void;
teamId: number;
type: string;
blockData: BlockData;
}
const UploadModal = () => {
const { teamId } = useTeamStore();

const { formData, reset } = useBlockContext();
const { closeModal } = useModalStore();

const UploadModal = ({ onClose, teamId, type, blockData }: UploadModalProps) => {
const [files, setFiles] = useState<File[]>([]);
const [fileUrls, setFileUrls] = useState<Files>({});
const [uploadStatus, setUploadStatus] = useState<{ [key: string]: boolean }>({});
const [isAllUploaded, setIsAllUploaded] = useState(true);

const { mutate: timeBlockMutate } = usePostTimeBlockMutation(teamId, type);
const { mutate: timeBlockMutate } = usePostTimeBlockMutation(+teamId, 'executive');
const { mutate: fileDeleteMutate } = useDeleteFileMutation();
const { createToast } = useToastStore();

Expand Down Expand Up @@ -77,19 +77,20 @@ const UploadModal = ({ onClose, teamId, type, blockData }: UploadModalProps) =>
};

const data = {
name: blockData.blockName,
name: formData.blockName,
color: getRandomColor(),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

요기 서버에서 컬러색상코드를 전달해주니까 그 값을 넘겨주는 방향으로 수정 부탁드립니다 ㅎㅎ

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

수정 완료 했습니다!

startDate: formatDatePost(blockData.dates.startDate),
endDate: formatDatePost(blockData.dates.endDate),
blockType: blockData.blockType,
startDate: formatDatePost(formData.startDate),
endDate: formatDatePost(formData.endDate),
blockType: formData.blockType,
files: fileUrls,
};

const handleSave = () => {
timeBlockMutate(data, {
onSuccess: () => {
onClose();
createToast('활동 블록이 생성되었습니다', 'success');
closeModal();
reset();
},
});
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import { useState } from 'react';
const useDateRange = (
initialStartDate = '',
initialEndDate = '',
onSetStartDate: (date: string | ((prev: string) => string)) => void,
onSetEndDate: (date: string | ((prev: string) => string)) => void,
onSetStartDate: (date: string) => void,
onSetEndDate: (date: string) => void,
onSetIsDateRangeValid: (isValid: boolean) => void
) => {
const [dates, setDates] = useState({ startDate: initialStartDate, endDate: initialEndDate });
Expand Down
26 changes: 8 additions & 18 deletions src/page/archiving/index/ArchivingPage.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import BlockModal from '@/page/archiving/createTimeBlock/component/Block/BlockModal';
import UploadModal from '@/page/archiving/createTimeBlock/component/Upload/UploadModal';
import { buttonStyle, contentStyle, daySectionStyle, timelineStyle } from '@/page/archiving/index/ArchivingPage.style';
import DaySection from '@/page/archiving/index/component/DaySection/DaySection';
import DocumentBar from '@/page/archiving/index/component/DocumentBar/DocumentBar';
Expand All @@ -16,10 +14,11 @@ import { useState } from 'react';
import AddIc from '@/common/asset/svg/add_btn.svg?react';
import Button from '@/common/component/Button/Button';
import Flex from '@/common/component/Flex/Flex';
import Modal from '@/common/component/Modal/Modal';
import { useModal, useOutsideClick } from '@/common/hook';
import { useOutsideClick } from '@/common/hook';
import { theme } from '@/common/style/theme/theme';

import { BlockFlow } from '@/shared/component/ModalFlow/BlockFlow';
import { useModalStore } from '@/shared/store/modal';
import { useTeamStore } from '@/shared/store/team';

const ArchivingPage = () => {
Expand Down Expand Up @@ -66,15 +65,10 @@ const ArchivingPage = () => {
const blockFloors = alignBlocks(timeBlocks, endDay, selectedMonth, currentYear);

// 블록 생성 모달 관련 코드
const { isOpen, openModal, closeModal, setCurrentContent, currentContent } = useModal();

const handleNext = (blockData: {
blockName: string;
blockType: string;
dates: { startDate: string; endDate: string };
}) => {
const type = 'executive';
setCurrentContent(<UploadModal onClose={closeModal} teamId={+teamId} type={type} blockData={blockData} />);
const openModal = useModalStore((state) => state.openModal);

const handleOpenBlockModal = () => {
openModal(<BlockFlow />);
};

return (
Expand Down Expand Up @@ -148,17 +142,13 @@ const ArchivingPage = () => {
</div>
</Flex>
<Flex css={{ zIndex: theme.zIndex.overlayTop, marginLeft: 'auto' }}>
<Button
variant="action"
css={buttonStyle(selectedBlock)}
onClick={() => openModal(<BlockModal onNext={handleNext} />)}>
<Button variant="action" css={buttonStyle(selectedBlock)} onClick={handleOpenBlockModal}>
<AddIc width={24} height={24} />
블록 생성
</Button>
</Flex>
</section>

<Modal isOpen={isOpen} children={currentContent} onClose={closeModal} />
<DocumentBar
selectedBlock={selectedBlock}
ref={sideBarRef}
Expand Down
44 changes: 20 additions & 24 deletions src/page/archiving/index/component/DocumentItem/DocumentItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,10 @@ import { ReactNode } from 'react';
import Download from '@/common/asset/svg/download.svg?react';
import TrashBox from '@/common/asset/svg/trash_box.svg?react';
import Flex from '@/common/component/Flex/Flex';
import Modal from '@/common/component/Modal/Modal';
import Text from '@/common/component/Text/Text';
import { useModal } from '@/common/hook';

import DeleteModal from '@/shared/component/DeleteModal/DeleteModal';
import { useModalStore } from '@/shared/store/modal';
import { useTeamStore } from '@/shared/store/team';

interface DocumentItemProps {
Expand All @@ -28,8 +27,6 @@ interface DocumentItemProps {
}

const DocumentItem = ({ documentId, children, selectedId, blockName, fileUrl, color }: DocumentItemProps) => {
const { isOpen, openModal, closeModal, currentContent } = useModal();

const fileName = children?.toString();

const { teamId } = useTeamStore();
Expand All @@ -46,30 +43,29 @@ const DocumentItem = ({ documentId, children, selectedId, blockName, fileUrl, co

const handleTrashClick = (e: React.MouseEvent<SVGSVGElement, MouseEvent>) => {
e.stopPropagation();
openModal(<DeleteModal title="docs" detail="docs" onClose={closeModal} teamId={+teamId} id={documentId} />);
// 모달 띄우기
const modalContent = <DeleteModal title="docs" detail="docs" teamId={+teamId} id={documentId} />;
useModalStore.getState().openModal(modalContent);
};

return (
<>
{/* eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions */}
<li css={containerStyle(selectedId)} onClick={onClickDocumentItem}>
{color && (
<div>
<Text tag="body8" css={blockNameTextStyle(color)}>
{blockName}
</Text>
</div>
)}
<Flex>
<Text tag="body6" css={fileNameStyle}>
{fileName}
/* eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions */
<li css={containerStyle(selectedId)} onClick={onClickDocumentItem}>
{color && (
<div>
<Text tag="body8" css={blockNameTextStyle(color)}>
{blockName}
</Text>
<Download width={20} height={20} css={{ cursor: 'pointer' }} onClick={handleDownloadClick} />
<TrashBox width={20} height={20} onClick={(e) => handleTrashClick(e)} css={{ cursor: 'pointer' }} />
</Flex>
</li>
<Modal isOpen={isOpen} children={currentContent} onClose={closeModal} />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오 요 modal 컴포넌트가 굉장히 애매했는데 이제 없앨수 있군요!
그러면 지금

  • 태그와 태그를 감싸고 있던 빈 <> 태그를 지워도 되겠네요~~!!

  • Copy link
    Contributor Author

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    맞아요! 빈태그도 지워줬습니다!!

    </>
    </div>
    )}
    <Flex>
    <Text tag="body6" css={fileNameStyle}>
    {fileName}
    </Text>
    <Download width={20} height={20} css={{ cursor: 'pointer' }} onClick={handleDownloadClick} />
    <TrashBox width={20} height={20} onClick={(e) => handleTrashClick(e)} css={{ cursor: 'pointer' }} />
    </Flex>
    </li>
    );
    };
    export default DocumentItem;
    Loading
    Loading