Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
59 changes: 0 additions & 59 deletions src/components/Modal/ColumnModifyModal.tsx

This file was deleted.

105 changes: 105 additions & 0 deletions src/components/Modal/ModifyColumnModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import { useQueryClient } from '@tanstack/react-query';
import { AxiosError } from 'axios';
import { useRouter } from 'next/router';
import { useState } from 'react';

import ModalActionButton from '@/components/Button/ModalActionButton';
import ModalCancelButton from '@/components/Button/ModalCancelButton';
import useModal from '@/hooks/useModal';
import { deleteColumn } from '@/services/deleteService';
import { putColumn } from '@/services/putService';
import { ModifyColumnModalProps } from '@/types/Modal.interface';

export default function ModifyColumnModal({ columnId, columnTitle = '', columns }: ModifyColumnModalProps) {
const { openModal, closeModal } = useModal();
const queryClient = useQueryClient();

const router = useRouter();
const { id: dashboardId } = router.query;
const [title, setTitle] = useState(columnTitle);
const [errorMessage, setErrorMessage] = useState('');
const columnNames = columns.map((column) => column.title);

const handleValidCheck = () => {
if (!title) {
setErrorMessage('이름을 입력해주세요');
} else if (title.length > 10) {
setErrorMessage('10자 이내로 입력해주세요');
} else if (columnNames.includes(title)) {
setErrorMessage('중복된 컬럼 이름입니다');
} else {
setErrorMessage('');
}
};

const handleModifyClick = async () => {
try {
await putColumn(columnId, { title });
queryClient.invalidateQueries({ queryKey: ['columns', dashboardId] });
openModal({ type: 'notification', modalProps: { text: '컬럼이 성공적으로 변경되었습니다.' } });
} catch (error) {
if (error instanceof AxiosError) {
setErrorMessage(error.response?.data.message || '컬럼 변경을 실패하였습니다.');
Copy link
Contributor Author

Choose a reason for hiding this comment

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

실패시 입력 하단에 에러메시지 뜨는 방식이 더 좋은 듯 해서 (대양님 코드 참고) 이 방식 사용했습니다.

} else {
setErrorMessage('컬럼 변경을 실패하였습니다.');
console.log(error);
}
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

이 try catch도 요청 보내는 모달마다 반복되어서, 묶을 수 있으면 좋을 것 같습니다!
그런데 다 메세지가 달라서 번거로울 수 있겠네요

Copy link
Contributor

Choose a reason for hiding this comment

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

혜원님!! 저 개인적인 질문 있습니다. 만약에 이런 부분 묶는다고 하신다면, 프로젝트 내에서 try catch 사용되는 모든 부분 확인해서 공통된 부분 찾아서 만드시는걸까요?? 저는 그런 식으로 하는데 더 똑똑하게 하는 방법이 있나해서 여쭤봅니다

Copy link
Contributor Author

@un0211 un0211 Jul 1, 2024

Choose a reason for hiding this comment

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

저도 그렇게 합니다!
뭔가 자꾸 똑같은 코드를 적다보면 or 디자인이 비슷해 보이는 게 많으면 공통부분 찾아서 만들어요.

이번에 말씀드린 건 모든 try catch보다는 모달에서 자꾸 똑같은 에러 핸들링이 사용되는 걸 합치는 건데,
함수 / 메세지가 각자 달라서 별로 의미 없을 것 같기도 합니다!!
만든다면 useAxiosWithHandling (fn, queryKey, successMessage, errorMessage) 이런 식으로 만들 수 있을 것 같아요..

};

const handleDeleteClick = async () => {
try {
await deleteColumn(columnId);
queryClient.invalidateQueries({ queryKey: ['columns', dashboardId] });
openModal({ type: 'notification', modalProps: { text: '컬럼이 삭제되었습니다.' } });
} catch (error) {
if (error instanceof AxiosError && error.response?.data.message) {
openModal({ type: 'notification', modalProps: { text: error.response.data.message } });
} else {
openModal({ type: 'notification', modalProps: { text: '컬럼이 삭제에 실패했습니다.' } });
console.log(error);
}
}
};

return (
<div className='modal w-[327px] md:w-[540px]'>
<h2 className='section-title'>컬럼 관리</h2>

<div className='my-6 md:mb-7 md:mt-8'>
<label className='label'>이름</label>
<input
type='text'
className={`input mt-[10px] ${errorMessage ? 'border-2 border-red' : ''}`}
placeholder='변경될 컬럼 이름을 입력해 주세요'
value={title}
onChange={(e) => setTitle(e.target.value)}
onBlur={handleValidCheck}
/>
{errorMessage && <p className='mt-2 text-sm text-red'>{errorMessage}</p>}
</div>

<div className='flex flex-col gap-4 md:flex-row md:items-end md:justify-between'>
<button
className='text-left text-sm text-gray-9f underline hover:font-bold active:text-gray-78'
onClick={() => {
openModal({
type: 'confirm',
modalProps: { text: '컬럼의 모든 카드가 삭제됩니다.', onActionClick: handleDeleteClick },
});
}}
>
삭제하기
</button>
<div className='flex justify-between md:justify-end md:gap-3'>
<ModalCancelButton type='button' onClick={closeModal}>
취소
</ModalCancelButton>
<ModalActionButton type='button' onClick={handleModifyClick} disabled={!!errorMessage}>
변경
</ModalActionButton>
</div>
</div>
</div>
);
}
10 changes: 6 additions & 4 deletions src/components/Modal/NewColumnModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ export default function NewColumnModal({ columns }: NewColumnModalProps) {
const handleValidCheck = () => {
if (!name) {
setErrorMessage('이름을 입력해주세요');
} else if (name.length > 10) {
setErrorMessage('10자 이내로 입력해주세요');
} else if (columnNames.includes(name)) {
setErrorMessage('중복된 컬럼 이름입니다');
} else {
Expand All @@ -36,10 +38,10 @@ export default function NewColumnModal({ columns }: NewColumnModalProps) {
queryClient.invalidateQueries({ queryKey: ['columns', id] });
openModal({ type: 'notification', modalProps: { text: '새로운 컬럼이 생성되었습니다!' } });
} catch (error) {
if (error instanceof AxiosError && error.response?.data.message) {
openModal({ type: 'notification', modalProps: { text: error.response.data.message } });
if (error instanceof AxiosError) {
setErrorMessage(error.response?.data.message || '컬럼 생성을 실패하였습니다.');
} else {
openModal({ type: 'notification', modalProps: { text: '컬럼 생성을 실패하였습니다.' } });
setErrorMessage('컬럼 생성을 실패하였습니다.');
console.log(error);
}
}
Expand All @@ -64,7 +66,7 @@ export default function NewColumnModal({ columns }: NewColumnModalProps) {
<ModalCancelButton type='button' onClick={closeModal}>
취소
</ModalCancelButton>
<ModalActionButton type='button' onClick={handlePostNewColumn} disabled={!!errorMessage}>
<ModalActionButton type='button' onClick={handlePostNewColumn} disabled={!(name && !errorMessage)}>
생성
</ModalActionButton>
</div>
Expand Down
8 changes: 4 additions & 4 deletions src/components/Modal/index.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import { useEffect } from 'react';
import { useSelector } from 'react-redux';

import ColumnModifyModal from './ColumnModifyModal';
import ConfirmModal from './ConfirmModal';
import InviteMemberModal from './InviteMemberModal';
import ModifyColumnModal from './ModifyColumnModal';
import NewColumnModal from './NewColumnModal';
import NewDashboardModal from './NewDashboardModal';
import NotificationModal from './NotificationModal';

import useModal from '@/hooks/useModal';
import { modalSelector } from '@/store/reducers/modalSlice';
import {
ColumnModifyModalProps,
ModifyColumnModalProps,
ConfirmModalProps,
InviteMemberModalProps,
NewColumnModalProps,
Expand Down Expand Up @@ -59,8 +59,8 @@ export default function Modal() {
case 'inviteMember':
return modalProps ? <InviteMemberModal modalProps={modalProps as InviteMemberModalProps} /> : null;

case 'columnModify':
return modalProps ? <ColumnModifyModal modalProps={modalProps as ColumnModifyModalProps} /> : null;
case 'modifyColumn':
return modalProps ? <ModifyColumnModal {...(modalProps as ModifyColumnModalProps)} /> : null;

default:
return <NotificationModal text='' />;
Expand Down
11 changes: 7 additions & 4 deletions src/containers/dashboard/Column.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import Image from 'next/image';
import React from 'react';

import Card from './Card';

Expand All @@ -11,9 +10,10 @@ import { Column as ColumnType } from '@/types/Column.interface';

interface ColumnProps {
column: ColumnType;
columns: ColumnType[];
}

function Column({ column }: ColumnProps) {
function Column({ column, columns }: ColumnProps) {
const { openModal } = useModal();
const {
data: cardList,
Expand Down Expand Up @@ -43,9 +43,12 @@ function Column({ column }: ColumnProps) {
</div>
{/* Column Edit Button */}
<button
className='duration-400 transition ease-in-out hover:rotate-90'
className='transition duration-300 ease-in-out hover:rotate-90'
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@wayandway 마침 딱 400 없고 300/500 있길래 300으로 해뒀습니다!

Copy link
Contributor

Choose a reason for hiding this comment

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

감사합니다 :)

onClick={() => {
openModal({ type: 'columnModify', modalProps: { columnId: column.id, columnTitle: column.title } });
openModal({
type: 'modifyColumn',
modalProps: { columnId: column.id, columnTitle: column.title, columns },
});
}}
>
<Image src='/icons/gear.svg' width={24} height={24} alt='톱니바퀴 아이콘' />
Expand Down
3 changes: 2 additions & 1 deletion src/containers/dashboard/ColumnsSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ export default function ColumnsSection({ id }: ColumnsSectionProps) {
<section>
<div className='block lg:flex lg:h-[calc(100dvh-70px)] lg:w-[calc(100dvw-270px)] lg:overflow-x-auto'>
<ul className='block lg:flex'>
{columns?.data && columns.data.map((column) => <Column key={column.id} column={column} />)}
{columns?.data &&
columns.data.map((column) => <Column key={column.id} column={column} columns={columns.data} />)}
{columns?.data.length === 0 && <p>컬럼이 없습니다.</p>}
</ul>
<div className='p-5'>
Expand Down
3 changes: 2 additions & 1 deletion src/types/Modal.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ export interface NewColumnModalProps extends ModalProps {
columns: Column[];
}

export interface ColumnModifyModalProps {
export interface ModifyColumnModalProps extends ModalProps {
columns: Column[];
columnTitle: string;
columnId: number;
}
Expand Down