diff --git a/package-lock.json b/package-lock.json
index 2923c63c..24395f4c 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -14977,6 +14977,126 @@
"optional": true
}
}
+ },
+ "node_modules/@next/swc-darwin-arm64": {
+ "version": "14.2.18",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.18.tgz",
+ "integrity": "sha512-tOBlDHCjGdyLf0ube/rDUs6VtwNOajaWV+5FV/ajPgrvHeisllEdymY/oDgv2cx561+gJksfMUtqf8crug7sbA==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-darwin-x64": {
+ "version": "14.2.18",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.18.tgz",
+ "integrity": "sha512-uJCEjutt5VeJ30jjrHV1VIHCsbMYnEqytQgvREx+DjURd/fmKy15NaVK4aR/u98S1LGTnjq35lRTnRyygglxoA==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-arm64-gnu": {
+ "version": "14.2.18",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.18.tgz",
+ "integrity": "sha512-IL6rU8vnBB+BAm6YSWZewc+qvdL1EaA+VhLQ6tlUc0xp+kkdxQrVqAnh8Zek1ccKHlTDFRyAft0e60gteYmQ4A==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-arm64-musl": {
+ "version": "14.2.18",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.18.tgz",
+ "integrity": "sha512-RCaENbIZqKKqTlL8KNd+AZV/yAdCsovblOpYFp0OJ7ZxgLNbV5w23CUU1G5On+0fgafrsGcW+GdMKdFjaRwyYA==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-x64-gnu": {
+ "version": "14.2.18",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.18.tgz",
+ "integrity": "sha512-3kmv8DlyhPRCEBM1Vavn8NjyXtMeQ49ID0Olr/Sut7pgzaQTo4h01S7Z8YNE0VtbowyuAL26ibcz0ka6xCTH5g==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-x64-musl": {
+ "version": "14.2.18",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.18.tgz",
+ "integrity": "sha512-mliTfa8seVSpTbVEcKEXGjC18+TDII8ykW4a36au97spm9XMPqQTpdGPNBJ9RySSFw9/hLuaCMByluQIAnkzlw==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-win32-arm64-msvc": {
+ "version": "14.2.18",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.18.tgz",
+ "integrity": "sha512-J5g0UFPbAjKYmqS3Cy7l2fetFmWMY9Oao32eUsBPYohts26BdrMUyfCJnZFQkX9npYaHNDOWqZ6uV9hSDPw9NA==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-win32-ia32-msvc": {
+ "version": "14.2.18",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.18.tgz",
+ "integrity": "sha512-Ynxuk4ZgIpdcN7d16ivJdjsDG1+3hTvK24Pp8DiDmIa2+A4CfhJSEHHVndCHok6rnLUzAZD+/UOKESQgTsAZGg==",
+ "cpu": [
+ "ia32"
+ ],
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
}
}
}
diff --git a/src/app/(crew)/crew/detail/[id]/_components/detail-crew-container.tsx b/src/app/(crew)/crew/detail/[id]/_components/detail-crew-container.tsx
index bd87cae7..e7e2b577 100644
--- a/src/app/(crew)/crew/detail/[id]/_components/detail-crew-container.tsx
+++ b/src/app/(crew)/crew/detail/[id]/_components/detail-crew-container.tsx
@@ -3,13 +3,14 @@
import { useEffect, useState } from 'react';
import { toast } from 'react-toastify';
import { useRouter } from 'next/navigation';
-import { Loader } from '@mantine/core';
import { useDisclosure } from '@mantine/hooks';
import { cancelCrew, joinCrew, leaveCrew } from '@/src/_apis/crew/crew-detail-apis';
import { useUser } from '@/src/_queries/auth/user-queries';
import { useGetCrewDetailQuery } from '@/src/_queries/crew/crew-detail-queries';
import { ApiError } from '@/src/utils/api';
+import Button from '@/src/components/common/input/button';
import ConfirmCancelModal from '@/src/components/common/modal/confirm-cancel-modal';
+import CrewDetailSkeleton from '@/src/components/common/skeleton/crew-detail-skeleton';
import { User } from '@/src/types/auth';
import DetailCrewPresenter from './detail-crew-presenter';
@@ -38,12 +39,8 @@ export default function DetailCrew({ id }: DetailCrewContainerProps) {
useEffect(() => {
if (data) {
- // confirmed 상태 계산
- if (data.participantCount !== undefined && data.totalCount !== undefined) {
- setIsConfirmed(data.participantCount === data.totalCount);
- }
+ setIsConfirmed(data.participantCount === data.totalCount);
- // Captain 및 멤버 여부 확인 (currentUserId 필요)
if (currentUserId) {
const captain = data.crewMembers.find((member) => member.captain);
const memberExists = data.crewMembers.some((member) => member.id === currentUserId);
@@ -114,29 +111,35 @@ export default function DetailCrew({ id }: DetailCrewContainerProps) {
});
};
- // TODO: 로딩, 에러처리 추후 개선
if (isLoading) {
- return
{message} 😞
+ +크루 정보를 찾을 수 없습니다
; - } - } catch (parseError) { - return{`Error ${fetchError.message}`}
; + if (fetchError.status === 404) { + router.push('/404'); + return null; } + toast.error(fetchError.message || '🚫 에러가 발생했습니다.'); + } else if (fetchError) { + toast.error('🚫 데이터 통신에 실패했습니다.'); } - return데이터 통신에 실패했습니다.
; - } - if (!data) { - return데이터를 불러올 수 없습니다.
; + const errorMessage = fetchError + ? '데이터를 불러오는 데 실패했습니다.' + : '데이터를 불러올 수 없습니다.'; + + return renderErrorState(errorMessage, '다시 시도', refetch); } return ( diff --git a/src/app/(crew)/crew/detail/[id]/_components/gathering-list-section.tsx b/src/app/(crew)/crew/detail/[id]/_components/gathering-list-section.tsx index 72d638bc..59d9c11f 100644 --- a/src/app/(crew)/crew/detail/[id]/_components/gathering-list-section.tsx +++ b/src/app/(crew)/crew/detail/[id]/_components/gathering-list-section.tsx @@ -3,11 +3,11 @@ import { useState } from 'react'; import { toast } from 'react-toastify'; import { useRouter } from 'next/navigation'; -import { Loader } from '@mantine/core'; import { addLike, removeLike } from '@/src/_apis/liked/liked-apis'; import { useGetGatheringListQuery } from '@/src/_queries/crew/gathering-list-queries'; import { ApiError } from '@/src/utils/api'; import ConfirmModal from '@/src/components/common/modal/confirm-modal'; +import GatheringSkeletonList from '@/src/components/common/skeleton/gathering-skeleton-list'; import CrewGatheringList from '@/src/components/gathering-list/crew-gathering-list'; interface GatheringListSectionProps { @@ -24,7 +24,7 @@ export default function GatheringListSection({ id }: GatheringListSectionProps) await addLike(gatheringId); } catch (apiError) { if (apiError instanceof ApiError) { - toast.error(`찜하기에 실패했습니다: ${apiError.message}`); + toast.error(`찜하기에 실패했습니다`); } } }; @@ -34,7 +34,7 @@ export default function GatheringListSection({ id }: GatheringListSectionProps) await removeLike(gatheringId); } catch (apiError) { if (apiError instanceof ApiError) { - toast.error(`찜하기 해제에 실패했습니다: ${apiError.message}`); + toast.error(`찜하기 해제에 실패했습니다`); } } }; @@ -48,11 +48,10 @@ export default function GatheringListSection({ id }: GatheringListSectionProps) refetch(); }; - // TODO: 추후 에러, 로딩 수정 if (isLoading) return (데이터가 없습니다.
+아직 등록된 약속이 없습니다!
+새로운 약속을 만들어보세요! 🙌
+