diff --git a/src/app/(auth)/layout.tsx b/src/app/(auth)/layout.tsx index 6d244fb..b43e1e7 100644 --- a/src/app/(auth)/layout.tsx +++ b/src/app/(auth)/layout.tsx @@ -4,7 +4,7 @@ export default function DashboardLayout({ children: React.ReactNode }) { return ( -
+
{children}
diff --git a/src/app/error.tsx b/src/app/error.tsx new file mode 100644 index 0000000..3eb337a --- /dev/null +++ b/src/app/error.tsx @@ -0,0 +1,62 @@ +'use client' + +import { useMounted } from '@hooks/useMounted' +import Image from 'next/image' +import { useTheme } from 'next-themes' + +export default function ErrorPage({ reset }: { reset?: () => void }) { + const { theme, systemTheme } = useTheme() + const mounted = useMounted() + if (!mounted) return null + + const currentTheme = theme === 'system' ? systemTheme : theme + const isDark = currentTheme === 'dark' + + return ( +
+
+ logo +
+
+ 에러가 발생했습니다 +
+
+ 문제가 발생했습니다. 잠시 후 다시 시도해 주세요. +
+ +
+ ) +} diff --git a/src/app/features/auth/api/authApi.ts b/src/app/features/auth/api/authApi.ts index 49b3576..bd401c1 100644 --- a/src/app/features/auth/api/authApi.ts +++ b/src/app/features/auth/api/authApi.ts @@ -1,4 +1,5 @@ -import authHttpClient from '@/app/shared/lib/axios' +import authHttpClient from '@api/axios' + import { User as SignupResponse } from '@/app/shared/types/user.type' import { LoginRequest, LoginResponse, SignupRequest } from '../types/auth.type' diff --git a/src/app/features/auth/api/authEndpoint.ts b/src/app/features/auth/api/authEndpoint.ts index ed55a9c..c2f84f4 100644 --- a/src/app/features/auth/api/authEndpoint.ts +++ b/src/app/features/auth/api/authEndpoint.ts @@ -1,4 +1,4 @@ export const AUTH_ENDPOINT = { - LOGIN: '/15-2/auth/login', - SIGNUP: '/15-2/users', + LOGIN: `/${process.env.NEXT_PUBLIC_TEAM_ID}/auth/login`, + SIGNUP: `/${process.env.NEXT_PUBLIC_TEAM_ID}/users`, } diff --git a/src/app/features/auth/components/LoginForm.tsx b/src/app/features/auth/components/LoginForm.tsx index ed93927..8ee0e02 100644 --- a/src/app/features/auth/components/LoginForm.tsx +++ b/src/app/features/auth/components/LoginForm.tsx @@ -1,6 +1,7 @@ 'use client' -import Input from '@components/Input' +import Input from '@components/common/Input/Input' +import PasswordInput from '@components/common/Input/PasswordInput' import { cn } from '@lib/cn' import { useForm } from 'react-hook-form' @@ -37,9 +38,8 @@ export default function LoginForm() { hasError={!!errors.email} errorMessage={errors.email?.message} /> - getValues('password')) + const validation = getConfirmPasswordValidation(() => getValues('password')) function handleAgree() { setIsChecked((prev) => !prev) @@ -60,9 +61,8 @@ export default function SignupForm() { hasError={!!errors.nickname} errorMessage={errors.nickname?.message} /> - - ({ mutationFn: login, onSuccess: async (response) => { + if (!process.env.NEXT_PUBLIC_TEAM_ID) { + throw new Error('NEXT_PUBLIC_TEAM_ID 환경변수가 설정되지 않았습니다.') + } + updateAuthState(response) showSuccess('로그인에 성공하셨습니다!') - await new Promise((resolve) => setTimeout(resolve, 400)) - router.push('/mydashboard') + + // ✅ 상태 반영을 위해 이벤트 큐로 넘김 + setTimeout(() => { + router.push('/mydashboard') + }, 0) }, onError: (error) => { if (axios.isAxiosError(error)) { diff --git a/src/app/features/auth/hooks/useSignupMutation.ts b/src/app/features/auth/hooks/useSignupMutation.ts index d0c9357..74d1ca8 100644 --- a/src/app/features/auth/hooks/useSignupMutation.ts +++ b/src/app/features/auth/hooks/useSignupMutation.ts @@ -10,6 +10,10 @@ import { signup } from '../api/authApi' import { SignupRequest } from '../types/auth.type' export function useSignupMutation() { + if (!process.env.NEXT_PUBLIC_TEAM_ID) { + throw new Error('NEXT_PUBLIC_TEAM_ID 환경변수가 설정되지 않았습니다.') + } + const router = useRouter() return useMutation({ diff --git a/src/app/features/dashboard/api/invitation.ts b/src/app/features/dashboard/api/invitation.ts index c0d9db2..ce54789 100644 --- a/src/app/features/dashboard/api/invitation.ts +++ b/src/app/features/dashboard/api/invitation.ts @@ -1,5 +1,5 @@ // src/app/features/dashboard/api/invitation.ts -import api from '@lib/axios' +import authHttpClient from '@api/axios' type InvitationRequest = { email: string @@ -7,7 +7,7 @@ type InvitationRequest = { } export const inviteUser = async ({ email, dashboardId }: InvitationRequest) => { - const response = await api.post( + const response = await authHttpClient.post( `/${process.env.NEXT_PUBLIC_TEAM_ID}/dashboards/${dashboardId}/invitations`, { email, diff --git a/src/app/features/dashboard/components/edit/DeleteDashboardButton.tsx b/src/app/features/dashboard/components/edit/DeleteDashboardButton.tsx index 63ea45b..c8f7502 100644 --- a/src/app/features/dashboard/components/edit/DeleteDashboardButton.tsx +++ b/src/app/features/dashboard/components/edit/DeleteDashboardButton.tsx @@ -1,6 +1,6 @@ 'use client' -import api from '@lib/axios' +import authHttpClient from '@api/axios' import { showError, showSuccess } from '@lib/toast' import { useMutation } from '@tanstack/react-query' import { useQueryClient } from '@tanstack/react-query' @@ -24,7 +24,7 @@ export default function DeleteDashboardButton({ if (!process.env.NEXT_PUBLIC_TEAM_ID) { throw new Error('NEXT_PUBLIC_TEAM_ID 환경변수가 설정되지 않았습니다.') } - await api.delete( + await authHttpClient.delete( `/${process.env.NEXT_PUBLIC_TEAM_ID}/dashboards/${dashboardId}`, ) }, diff --git a/src/app/features/dashboard/components/edit/EditInvitation.tsx b/src/app/features/dashboard/components/edit/EditInvitation.tsx index 58ea12a..311e9e0 100644 --- a/src/app/features/dashboard/components/edit/EditInvitation.tsx +++ b/src/app/features/dashboard/components/edit/EditInvitation.tsx @@ -1,7 +1,7 @@ 'use client' +import authHttpClient from '@api/axios' import Tooltip from '@components/common/header/Collaborator/Tooltip' -import api from '@lib/axios' import { cn } from '@lib/cn' import { showError, showSuccess } from '@lib/toast' import { useModalStore } from '@store/useModalStore' @@ -43,7 +43,7 @@ export default function EditInvitation() { queryKey: ['invitations', teamId, dashboardId], queryFn: async () => { if (!teamId || !dashboardId) return [] - const res = await api.get<{ invitations: Invitation[] }>( + const res = await authHttpClient.get<{ invitations: Invitation[] }>( `/${teamId}/dashboards/${dashboardId}/invitations`, ) return res.data.invitations @@ -66,7 +66,7 @@ export default function EditInvitation() { mutationFn: async (invitationId: number) => { if (!teamId || !dashboardId) throw new Error('teamId 또는 dashboardId가 없습니다.') - await api.delete( + await authHttpClient.delete( `/${teamId}/dashboards/${dashboardId}/invitations/${invitationId}`, ) }, diff --git a/src/app/features/dashboard/components/edit/EditMember.tsx b/src/app/features/dashboard/components/edit/EditMember.tsx index 2c05045..e06381b 100644 --- a/src/app/features/dashboard/components/edit/EditMember.tsx +++ b/src/app/features/dashboard/components/edit/EditMember.tsx @@ -1,6 +1,6 @@ 'use client' -import authHttpClient from '@lib/axios' +import authHttpClient from '@api/axios' import { cn } from '@lib/cn' import { getTeamId } from '@lib/getTeamId' import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query' diff --git a/src/app/features/dashboard_Id/api/deleteCard.ts b/src/app/features/dashboard_Id/api/deleteCard.ts index b6adfa1..2db2727 100644 --- a/src/app/features/dashboard_Id/api/deleteCard.ts +++ b/src/app/features/dashboard_Id/api/deleteCard.ts @@ -1,4 +1,4 @@ -import authHttpClient from '@/app/shared/lib/axios' +import authHttpClient from '@api/axios' import { ApiResponse } from '../type/ApiResponse' diff --git a/src/app/features/dashboard_Id/api/deleteColumn.ts b/src/app/features/dashboard_Id/api/deleteColumn.ts index cbed1d8..1a1526f 100644 --- a/src/app/features/dashboard_Id/api/deleteColumn.ts +++ b/src/app/features/dashboard_Id/api/deleteColumn.ts @@ -1,4 +1,4 @@ -import authHttpClient from '@/app/shared/lib/axios' +import authHttpClient from '@api/axios' export async function deleteColumn(columnId: number): Promise { await authHttpClient.delete( diff --git a/src/app/features/dashboard_Id/api/deleteComment.ts b/src/app/features/dashboard_Id/api/deleteComment.ts index b4ec240..61ab98b 100644 --- a/src/app/features/dashboard_Id/api/deleteComment.ts +++ b/src/app/features/dashboard_Id/api/deleteComment.ts @@ -1,4 +1,4 @@ -import authHttpClient from '@/app/shared/lib/axios' +import authHttpClient from '@api/axios' import { ApiResponse } from '../type/ApiResponse' diff --git a/src/app/features/dashboard_Id/api/fetchCards.ts b/src/app/features/dashboard_Id/api/fetchCards.ts index 909ee07..6a86d3d 100644 --- a/src/app/features/dashboard_Id/api/fetchCards.ts +++ b/src/app/features/dashboard_Id/api/fetchCards.ts @@ -1,4 +1,4 @@ -import authHttpClient from '@/app/shared/lib/axios' +import authHttpClient from '@api/axios' import { CardResponse } from '../type/Card.type' diff --git a/src/app/features/dashboard_Id/api/fetchColumns.ts b/src/app/features/dashboard_Id/api/fetchColumns.ts index dd741d2..667891e 100644 --- a/src/app/features/dashboard_Id/api/fetchColumns.ts +++ b/src/app/features/dashboard_Id/api/fetchColumns.ts @@ -1,4 +1,4 @@ -import authHttpClient from '@/app/shared/lib/axios' +import authHttpClient from '@api/axios' import { Column, ColumnsResponse } from '../type/Column.type' diff --git a/src/app/features/dashboard_Id/api/fetchComments.ts b/src/app/features/dashboard_Id/api/fetchComments.ts index c2f2284..075ce93 100644 --- a/src/app/features/dashboard_Id/api/fetchComments.ts +++ b/src/app/features/dashboard_Id/api/fetchComments.ts @@ -1,4 +1,4 @@ -import authHttpClient from '@/app/shared/lib/axios' +import authHttpClient from '@api/axios' import { CommentsResponse } from '../type/Comment.type' diff --git a/src/app/features/dashboard_Id/api/fetchMembers.ts b/src/app/features/dashboard_Id/api/fetchMembers.ts index ada311c..e95e05c 100644 --- a/src/app/features/dashboard_Id/api/fetchMembers.ts +++ b/src/app/features/dashboard_Id/api/fetchMembers.ts @@ -1,4 +1,4 @@ -import authHttpClient from '@/app/shared/lib/axios' +import authHttpClient from '@api/axios' import { Member, MembersResponse } from '../type/Member.type' diff --git a/src/app/features/dashboard_Id/api/postCard.ts b/src/app/features/dashboard_Id/api/postCard.ts index fc1d14b..fd01d1b 100644 --- a/src/app/features/dashboard_Id/api/postCard.ts +++ b/src/app/features/dashboard_Id/api/postCard.ts @@ -1,4 +1,4 @@ -import authHttpClient from '@/app/shared/lib/axios' +import authHttpClient from '@api/axios' import { CardFormData } from '../type/CardFormData.type' diff --git a/src/app/features/dashboard_Id/api/postCardImage.ts b/src/app/features/dashboard_Id/api/postCardImage.ts index 5188f0b..7a3d108 100644 --- a/src/app/features/dashboard_Id/api/postCardImage.ts +++ b/src/app/features/dashboard_Id/api/postCardImage.ts @@ -1,4 +1,4 @@ -import authHttpClient from '@/app/shared/lib/axios' +import authHttpClient from '@api/axios' // ✅ 카드 이미지 파일 업로드 시 - 카드 생성 요청에(post) 전달 가능한 형태의 데이터로, 응답 받아서 사용할 예정 export async function postCardImages( diff --git a/src/app/features/dashboard_Id/api/postColumn.ts b/src/app/features/dashboard_Id/api/postColumn.ts index f5613c0..f67709a 100644 --- a/src/app/features/dashboard_Id/api/postColumn.ts +++ b/src/app/features/dashboard_Id/api/postColumn.ts @@ -1,4 +1,4 @@ -import authHttpClient from '@/app/shared/lib/axios' +import authHttpClient from '@api/axios' import { CreateColumnRequest, CreateColumnResponse } from '../type/Column.type' diff --git a/src/app/features/dashboard_Id/api/postComment.ts b/src/app/features/dashboard_Id/api/postComment.ts index 33394ba..5ddcd88 100644 --- a/src/app/features/dashboard_Id/api/postComment.ts +++ b/src/app/features/dashboard_Id/api/postComment.ts @@ -1,4 +1,4 @@ -import authHttpClient from '@/app/shared/lib/axios' +import authHttpClient from '@api/axios' import { CommentResponse, PutCommentForm } from '../type/CommentFormData.type' diff --git a/src/app/features/dashboard_Id/api/putCard.ts b/src/app/features/dashboard_Id/api/putCard.ts index 6b00802..77c8d86 100644 --- a/src/app/features/dashboard_Id/api/putCard.ts +++ b/src/app/features/dashboard_Id/api/putCard.ts @@ -1,4 +1,4 @@ -import authHttpClient from '@/app/shared/lib/axios' +import authHttpClient from '@api/axios' import { ApiResponse } from '../type/ApiResponse' import { CardModifyFormData } from '../type/CardFormData.type' diff --git a/src/app/features/dashboard_Id/api/putComment.ts b/src/app/features/dashboard_Id/api/putComment.ts index bb2965b..7751792 100644 --- a/src/app/features/dashboard_Id/api/putComment.ts +++ b/src/app/features/dashboard_Id/api/putComment.ts @@ -1,4 +1,4 @@ -import authHttpClient from '@/app/shared/lib/axios' +import authHttpClient from '@api/axios' import { CommentResponse, PutCommentForm } from '../type/CommentFormData.type' diff --git a/src/app/features/dashboard_Id/api/updateCardColumn.ts b/src/app/features/dashboard_Id/api/updateCardColumn.ts index ba8d4b5..2841553 100644 --- a/src/app/features/dashboard_Id/api/updateCardColumn.ts +++ b/src/app/features/dashboard_Id/api/updateCardColumn.ts @@ -1,4 +1,4 @@ -import authHttpClient from '@/app/shared/lib/axios' +import authHttpClient from '@api/axios' // 카드 이동 - 해당 카드의 컬럼ID를 변경하는 방식(PUT) export async function updateCardColumn( diff --git a/src/app/features/dashboard_Id/api/updateColumn.ts b/src/app/features/dashboard_Id/api/updateColumn.ts index e9445e6..48bc89d 100644 --- a/src/app/features/dashboard_Id/api/updateColumn.ts +++ b/src/app/features/dashboard_Id/api/updateColumn.ts @@ -1,4 +1,4 @@ -import authHttpClient from '@/app/shared/lib/axios' +import authHttpClient from '@api/axios' import { UpdateColumnRequest, UpdateColumnResponse } from '../type/Column.type' diff --git a/src/app/features/landing/components/Footer.tsx b/src/app/features/landing/components/Footer.tsx index 8225c45..b0ed45b 100644 --- a/src/app/features/landing/components/Footer.tsx +++ b/src/app/features/landing/components/Footer.tsx @@ -1,3 +1,5 @@ +'use client' + import GithubIcon from './GithubIcon' export default function Footer() { diff --git a/src/app/features/landing/components/Header.tsx b/src/app/features/landing/components/Header.tsx index 0c87979..5fb5aef 100644 --- a/src/app/features/landing/components/Header.tsx +++ b/src/app/features/landing/components/Header.tsx @@ -4,12 +4,13 @@ import ThemeToggle from '@components/ThemeToggle' import Link from 'next/link' import Logo from './Logo' + export default function Header() { return (