diff --git a/components/DarkmodeToggle.tsx b/components/DarkmodeToggle.tsx index ddaeefdb..9149326f 100644 --- a/components/DarkmodeToggle.tsx +++ b/components/DarkmodeToggle.tsx @@ -28,7 +28,7 @@ export default function DarkModeToggle() { onClick={() => setIsDarkMode((prev) => !prev)} > 다크 모드 전환 ))} -
- {name} - 등록일 : {dateConversion(createdAt)} - | - - 최근 수정일 : {dateConversion(updatedAt)} - +
+ {name} +
+
+ 등록일 : {dateConversion(createdAt)} + | + 최근 수정일 : {dateConversion(updatedAt)} +
- + +
@@ -157,7 +159,8 @@ export default function BoardDetailCard({ width={500} height={300} priority - className="mb-5 h-[300px] w-[500px] mo:mb-[15px] mo:h-auto mo:w-[295px]" + className="h-[300px]] mb-5 w-auto mo:mb-[15px] mo:h-[177px]" + sizes="(max-width: 743px) 295px, 500px" />
diff --git a/components/boards.page/BoardList.tsx b/components/boards.page/BoardList.tsx index e00c54c7..b88e98b5 100644 --- a/components/boards.page/BoardList.tsx +++ b/components/boards.page/BoardList.tsx @@ -9,7 +9,7 @@ import BoardItem from './BoardItem'; */ export default function BoardList({ data = [] }: BoardListResponse) { const tableStyles = - 'grid grid-cols-[50px_2fr_120px_120px_130px] ta:grid-cols-[50px 2fr 70px 100px 110px] py-[11px] mo:py-[14px] border-b items-center text-16 pc:px-[30px] ta:px-[10px]'; + 'grid grid-cols-[50px_2fr_120px_120px_130px] ta:grid-cols-[50px_2fr_70px_100px_110px] py-[11px] mo:py-[14px] border-b items-center text-16 pc:px-[30px] ta:px-[10px]'; return (
diff --git a/components/boards.page/Comment.tsx b/components/boards.page/Comment.tsx index d4658422..6a269f29 100644 --- a/components/boards.page/Comment.tsx +++ b/components/boards.page/Comment.tsx @@ -59,11 +59,11 @@ export default function Comment({ user profile -
+
{name} diff --git a/pages/boards/[articleId].tsx b/pages/boards/[articleId].tsx index 0b3b1017..60771028 100644 --- a/pages/boards/[articleId].tsx +++ b/pages/boards/[articleId].tsx @@ -27,6 +27,7 @@ import { } from '@/services/api/commentAPI'; import { CommentsData, CommentType } from 'types/board'; import SnackBar, { SnackBarProps } from '@/components/SnackBar'; +import ModalDefault from '@/components/Modal/ModalDefault'; export default function BoardsDetails() { const [boardData, setBoardData] = useState(null); @@ -38,6 +39,8 @@ export default function BoardsDetails() { const [snackStyled, setSnackStyled] = useState(undefined); + const [isModal, setIsModal] = useState(false); + const [commentToDelete, setCommentToDelete] = useState(null); const router = useRouter(); const { articleId } = router.query; const { isAuthenticated } = useProfileContext(); @@ -172,14 +175,28 @@ export default function BoardsDetails() { }; // 댓글 삭제 핸들러 - const handleDelete = async (id: number) => { - try { - await deleteCommentMutation.mutateAsync(id); - } catch (error) { - console.error('댓글을 삭제하지 못했습니다.', error); + const handleDelete = async () => { + if (commentToDelete !== null) { + try { + await deleteCommentMutation.mutateAsync(commentToDelete); + setIsModal(false); + setCommentToDelete(null); + } catch (error) { + console.error('댓글을 삭제하지 못했습니다.', error); + } } }; + const handleDeleteClick = (id: number) => { + setCommentToDelete(id); + setIsModal(true); + }; + + const handleModalClose = () => { + setIsModal(false); + setCommentToDelete(null); + }; + // 게시글 데이터 로딩 상태 if (!boardData) { return
게시글을 불러오는 중입니다...
; @@ -247,7 +264,7 @@ export default function BoardsDetails() { onclick={{ update: (newContent: string) => handleUpdate(item.id, newContent), - delete: () => handleDelete(item.id), + delete: () => handleDeleteClick(item.id), }} isOwner={item.writer.id === userId} /> @@ -275,6 +292,18 @@ export default function BoardsDetails() { > {snackBarMessage} + + + + ); diff --git a/pages/boards/index.tsx b/pages/boards/index.tsx index db4f3359..56a80b2a 100644 --- a/pages/boards/index.tsx +++ b/pages/boards/index.tsx @@ -74,7 +74,8 @@ export default function Boards({ const [likeBoards] = useState(initialLikeBoards); const [currentPage, setCurrentPage] = useState(1); const [value, setValue] = useState(''); - const [selectedOption, setSelectedOption] = useState('최신순'); // 옵션 상태 추가 + const [searchValue, setSearchValue] = useState(''); + const [selectedOption, setSelectedOption] = useState('최신순'); const [snackBarOpen, setSnackBarOpen] = useState(false); const [snackBarMessage, setSnackBarMessage] = useState(''); const [snackStyled, setSnackStyled] = @@ -93,6 +94,7 @@ export default function Boards({ orderBy, pageSize: PAGE_SIZE, page: currentPage, + keyword: searchValue, }); if (Array.isArray(res.list) && res.list.length > 0) { setBoards(res.list); @@ -104,19 +106,10 @@ export default function Boards({ fetchBoards().catch((error) => console.error('게시글 데이터를 불러오지 못했습니다 :', error) ); - }, [selectedOption, currentPage]); + }, [selectedOption, currentPage, searchValue]); const handleSearchSubmit = async () => { - const res = await getBoards({ - keyword: value, - pageSize: PAGE_SIZE, - page: currentPage, - }); - if (Array.isArray(res.list) && res.list.length > 0) { - setBoards(res.list); - } else { - setBoards([]); - } + setSearchValue(value); }; const handleOptionSelect = (option: string) => { @@ -136,9 +129,9 @@ export default function Boards({ }; const emptyListText = - value === '' + searchValue === '' ? '게시글이 존재하지 않습니다.' - : `${value}와(과) 일치하는 검색 결과가 없습니다.`; + : `${searchValue}와(과) 일치하는 검색 결과가 없습니다.`; const pxTablet = 'ta:px-[60px]'; diff --git a/pages/updateboard/[articleId].tsx b/pages/updateboard/[articleId].tsx index cc5e6dc3..109adbaf 100644 --- a/pages/updateboard/[articleId].tsx +++ b/pages/updateboard/[articleId].tsx @@ -75,8 +75,7 @@ export default function UpdateBoard() { // 작성 폼 서브밋 함수 const handleSubmit = async (e: FormEvent) => { e.preventDefault(); - // 썸네일 이미지 주소 - let imageUrl = ''; + let imageUrl = getImage; if (imageFile) { formData.append('image', imageFile); @@ -102,11 +101,20 @@ export default function UpdateBoard() { } try { - await patchBoard(articleId as number | string, { + const updateData: { + title: string; + content: string; + image?: string | null; + } = { title, content, - image: imageUrl, - }); + }; + + if (imageFile) { + updateData.image = imageUrl; + } + + await patchBoard(articleId as number | string, updateData); if (typeof articleId === 'string') { setSnackStyled('success'); setSnackBarMessage( diff --git a/types/board.ts b/types/board.ts index d9378377..f0a13f60 100644 --- a/types/board.ts +++ b/types/board.ts @@ -20,7 +20,7 @@ export interface BoardBase extends BaseEntity { export interface BoardCreateData { title: string; content: string; - image: string; + image?: string | null; } export interface Board extends BoardBase { diff --git a/utils/dateConversion.ts b/utils/dateConversion.ts index 0355664b..b1760cbc 100644 --- a/utils/dateConversion.ts +++ b/utils/dateConversion.ts @@ -8,8 +8,14 @@ export default function dateConversion(isoString: string): string { const createdDate = new Date(isoString); // 생성일 const currentDate = new Date(); // 현재 날짜 const timeDifference = currentDate.getTime() - createdDate.getTime(); // 오차 계산 - const hoursDifference = Math.floor(timeDifference / (1000 * 60 * 60)); // 시간 환산 - const minutesDifference = Math.floor(timeDifference / (1000 * 60)); // 분 환산 + const hoursDifference = Math.max( + Math.floor(timeDifference / (1000 * 60 * 60)), + 0 + ); + const minutesDifference = Math.max( + Math.floor(timeDifference / (1000 * 60)), + 0 + ); if (hoursDifference < 1) { return `${minutesDifference}분 전`; // 생성한지 1시간이 안되었을 때