Feat: auth, project, workspace 훅 구현
This commit is contained in:
parent
2e80356cf5
commit
8e74ef4428
104
frontend/src/hooks/useAuthHooks.ts
Normal file
104
frontend/src/hooks/useAuthHooks.ts
Normal file
@ -0,0 +1,104 @@
|
||||
import { useQuery, UseQueryResult, useMutation, useQueryClient, UseMutationResult } from '@tanstack/react-query';
|
||||
import { AxiosError } from 'axios';
|
||||
import useAuthStore from '@/stores/useAuthStore';
|
||||
import { reissueTokenApi, fetchProfileApi } from '@/api/authApi';
|
||||
import { useState, useEffect } from 'react';
|
||||
|
||||
interface TokenResponse {
|
||||
status: number;
|
||||
code: number;
|
||||
message: string;
|
||||
data: {
|
||||
accessToken: string;
|
||||
};
|
||||
errors: Array<{
|
||||
field: string;
|
||||
code: string;
|
||||
message: string;
|
||||
objectName: string;
|
||||
}>;
|
||||
isSuccess: boolean;
|
||||
}
|
||||
|
||||
interface ProfileResponse {
|
||||
status: number;
|
||||
code: number;
|
||||
message: string;
|
||||
data: {
|
||||
id: number;
|
||||
nickname: string;
|
||||
profileImage: string;
|
||||
};
|
||||
errors: Array<{
|
||||
field: string;
|
||||
code: string;
|
||||
message: string;
|
||||
objectName: string;
|
||||
}>;
|
||||
isSuccess: boolean;
|
||||
}
|
||||
|
||||
interface ErrorResponse {
|
||||
message: string;
|
||||
}
|
||||
|
||||
export const useReissueToken = (): UseMutationResult<TokenResponse, AxiosError<ErrorResponse>> => {
|
||||
const queryClient = useQueryClient();
|
||||
const { setLoggedIn } = useAuthStore();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: reissueTokenApi,
|
||||
onSuccess: (data) => {
|
||||
setLoggedIn(true, data.data.accessToken);
|
||||
queryClient.invalidateQueries({ queryKey: ['profile'] });
|
||||
},
|
||||
onError: (error) => {
|
||||
console.error('토큰 재발급 실패:', error?.response?.data?.message || '알 수 없는 오류');
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const useProfile = (): UseQueryResult<ProfileResponse, AxiosError<ErrorResponse>> => {
|
||||
const { accessToken, setProfile } = useAuthStore();
|
||||
|
||||
return useQuery<ProfileResponse, AxiosError<ErrorResponse>>({
|
||||
queryKey: ['profile'],
|
||||
queryFn: fetchProfileApi,
|
||||
enabled: !!accessToken,
|
||||
select: (data) => {
|
||||
if (data.isSuccess) {
|
||||
setProfile({
|
||||
id: data.data.id,
|
||||
nickname: data.data.nickname,
|
||||
profileImage: data.data.profileImage,
|
||||
});
|
||||
}
|
||||
return data;
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const useFetchProfile = () => {
|
||||
const { profile, setProfile } = useAuthStore();
|
||||
const [isFetched, setIsFetched] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!profile.id && !isFetched) {
|
||||
fetchProfileApi()
|
||||
.then((data) => {
|
||||
if (data?.isSuccess && data.data) {
|
||||
setProfile({
|
||||
id: data.data.id,
|
||||
nickname: data.data.nickname,
|
||||
profileImage: data.data.profileImage,
|
||||
});
|
||||
setIsFetched(true);
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
alert('프로필을 가져오는 중 오류가 발생했습니다. 다시 시도해주세요.');
|
||||
console.error('프로필 가져오기 실패:', error);
|
||||
});
|
||||
}
|
||||
}, [profile.id, setProfile, isFetched]);
|
||||
};
|
150
frontend/src/hooks/useProjectHooks.ts
Normal file
150
frontend/src/hooks/useProjectHooks.ts
Normal file
@ -0,0 +1,150 @@
|
||||
import { useQuery, UseQueryResult, useMutation, UseMutationResult, useQueryClient } from '@tanstack/react-query';
|
||||
import { AxiosError } from 'axios';
|
||||
import {
|
||||
getProjectApi,
|
||||
updateProjectApi,
|
||||
deleteProjectApi,
|
||||
getAllProjectsApi,
|
||||
createProjectApi,
|
||||
addProjectMemberApi,
|
||||
removeProjectMemberApi,
|
||||
} from '@/api/projectApi';
|
||||
|
||||
interface Project {
|
||||
id: number;
|
||||
title: string;
|
||||
workspaceId: number;
|
||||
projectType: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
interface ProjectsResponse {
|
||||
status: number;
|
||||
code: number;
|
||||
message: string;
|
||||
data: {
|
||||
workspaceResponses: Project[];
|
||||
};
|
||||
errors: Array<{
|
||||
field: string;
|
||||
code: string;
|
||||
message: string;
|
||||
objectName: string;
|
||||
}>;
|
||||
isSuccess: boolean;
|
||||
}
|
||||
|
||||
interface ErrorResponse {
|
||||
message: string;
|
||||
}
|
||||
|
||||
export const useGetProject = (
|
||||
projectId: number,
|
||||
memberId: number
|
||||
): UseQueryResult<ProjectsResponse, AxiosError<ErrorResponse>> => {
|
||||
return useQuery<ProjectsResponse, AxiosError<ErrorResponse>>({
|
||||
queryKey: ['project', projectId],
|
||||
queryFn: () => getProjectApi(projectId, memberId),
|
||||
});
|
||||
};
|
||||
|
||||
export const useUpdateProject = (): UseMutationResult<
|
||||
ProjectsResponse,
|
||||
AxiosError<ErrorResponse>,
|
||||
{ projectId: number; memberId: number; data: { title: string; projectType: string } }
|
||||
> => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: ({ projectId, memberId, data }) => updateProjectApi(projectId, memberId, data),
|
||||
onSuccess: (data) => {
|
||||
const project = data.data?.workspaceResponses?.[0];
|
||||
if (project) {
|
||||
queryClient.invalidateQueries({ queryKey: ['project', project.id] });
|
||||
} else {
|
||||
console.error('프로젝트 데이터가 없습니다.');
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const useDeleteProject = (): UseMutationResult<
|
||||
ProjectsResponse,
|
||||
AxiosError<ErrorResponse>,
|
||||
{ projectId: number; memberId: number }
|
||||
> => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: ({ projectId, memberId }) => deleteProjectApi(projectId, memberId),
|
||||
onSuccess: (data) => {
|
||||
const project = data.data?.workspaceResponses?.[0];
|
||||
if (project) {
|
||||
queryClient.invalidateQueries({ queryKey: ['project', project.id] });
|
||||
} else {
|
||||
console.error('프로젝트 데이터가 없습니다.');
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const useGetAllProjects = (
|
||||
workspaceId: number,
|
||||
memberId: number,
|
||||
lastProjectId?: number,
|
||||
limit: number = 10
|
||||
): UseQueryResult<ProjectsResponse, AxiosError<ErrorResponse>> => {
|
||||
return useQuery<ProjectsResponse, AxiosError<ErrorResponse>>({
|
||||
queryKey: ['projects', workspaceId],
|
||||
queryFn: () => getAllProjectsApi(workspaceId, memberId, lastProjectId, limit),
|
||||
});
|
||||
};
|
||||
|
||||
export const useCreateProject = (): UseMutationResult<
|
||||
ProjectsResponse,
|
||||
AxiosError<ErrorResponse>,
|
||||
{ workspaceId: number; memberId: number; data: { title: string; projectType: string } }
|
||||
> => {
|
||||
return useMutation({
|
||||
mutationFn: ({ workspaceId, memberId, data }) => createProjectApi(workspaceId, memberId, data),
|
||||
});
|
||||
};
|
||||
|
||||
export const useAddProjectMember = (): UseMutationResult<
|
||||
ProjectsResponse,
|
||||
AxiosError<ErrorResponse>,
|
||||
{ projectId: number; memberId: number; newMemberId: number; privilegeType: string }
|
||||
> => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: ({ projectId, memberId, newMemberId, privilegeType }) =>
|
||||
addProjectMemberApi(projectId, memberId, newMemberId, privilegeType),
|
||||
onSuccess: (data) => {
|
||||
const project = data.data?.workspaceResponses?.[0];
|
||||
if (project) {
|
||||
queryClient.invalidateQueries({ queryKey: ['project', project.id] });
|
||||
} else {
|
||||
console.error('프로젝트 데이터가 없습니다.');
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const useRemoveProjectMember = (): UseMutationResult<
|
||||
ProjectsResponse,
|
||||
AxiosError<ErrorResponse>,
|
||||
{ projectId: number; memberId: number; targetMemberId: number }
|
||||
> => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: ({ projectId, memberId, targetMemberId }) =>
|
||||
removeProjectMemberApi(projectId, memberId, targetMemberId),
|
||||
onSuccess: (data) => {
|
||||
const project = data.data?.workspaceResponses?.[0];
|
||||
if (project) {
|
||||
queryClient.invalidateQueries({ queryKey: ['project', project.id] });
|
||||
} else {
|
||||
console.error('프로젝트 데이터가 없습니다.');
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
152
frontend/src/hooks/useWorkspaceHooks.ts
Normal file
152
frontend/src/hooks/useWorkspaceHooks.ts
Normal file
@ -0,0 +1,152 @@
|
||||
import { useQuery, UseQueryResult, useMutation, UseMutationResult, useQueryClient } from '@tanstack/react-query';
|
||||
import { AxiosError } from 'axios';
|
||||
import {
|
||||
getWorkspaceApi,
|
||||
updateWorkspaceApi,
|
||||
deleteWorkspaceApi,
|
||||
getAllWorkspacesApi,
|
||||
createWorkspaceApi,
|
||||
addWorkspaceMemberApi,
|
||||
removeWorkspaceMemberApi,
|
||||
} from '@/api/workspaceApi';
|
||||
|
||||
interface WorkspaceResponse {
|
||||
status: number;
|
||||
code: number;
|
||||
message: string;
|
||||
data: {
|
||||
id: number;
|
||||
memberId: string;
|
||||
title: string;
|
||||
content: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
};
|
||||
errors: Array<{
|
||||
field: string;
|
||||
code: string;
|
||||
message: string;
|
||||
objectName: string;
|
||||
}>;
|
||||
isSuccess: boolean;
|
||||
}
|
||||
interface Workspace {
|
||||
id: number;
|
||||
memberId: string;
|
||||
title: string;
|
||||
content: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
interface GetAllWorkspacesResponse {
|
||||
status: number;
|
||||
code: number;
|
||||
message: string;
|
||||
data: {
|
||||
workspaceResponses: Workspace[];
|
||||
};
|
||||
errors: Array<{
|
||||
field: string;
|
||||
code: string;
|
||||
message: string;
|
||||
objectName: string;
|
||||
}>;
|
||||
isSuccess: boolean;
|
||||
}
|
||||
|
||||
interface ErrorResponse {
|
||||
message: string;
|
||||
}
|
||||
|
||||
export const useGetWorkspace = (
|
||||
workspaceId: number,
|
||||
memberId: number
|
||||
): UseQueryResult<WorkspaceResponse, AxiosError<ErrorResponse>> => {
|
||||
return useQuery<WorkspaceResponse, AxiosError<ErrorResponse>>({
|
||||
queryKey: ['workspace', workspaceId],
|
||||
queryFn: () => getWorkspaceApi(workspaceId, memberId),
|
||||
});
|
||||
};
|
||||
|
||||
export const useUpdateWorkspace = (): UseMutationResult<
|
||||
WorkspaceResponse,
|
||||
AxiosError<ErrorResponse>,
|
||||
{ workspaceId: number; memberId: number; data: { title: string; content: string } }
|
||||
> => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: ({ workspaceId, memberId, data }) => updateWorkspaceApi(workspaceId, memberId, data),
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ['workspace'] });
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const useDeleteWorkspace = (): UseMutationResult<
|
||||
WorkspaceResponse,
|
||||
AxiosError<ErrorResponse>,
|
||||
{ workspaceId: number; memberId: number }
|
||||
> => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: ({ workspaceId, memberId }) => deleteWorkspaceApi(workspaceId, memberId),
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ['workspace'] });
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const useGetAllWorkspaces = (
|
||||
memberId: number,
|
||||
lastWorkspaceId?: number,
|
||||
limit?: number
|
||||
): UseQueryResult<GetAllWorkspacesResponse, AxiosError<ErrorResponse>> => {
|
||||
return useQuery<GetAllWorkspacesResponse, AxiosError<ErrorResponse>>({
|
||||
queryKey: ['workspaces'],
|
||||
queryFn: () => getAllWorkspacesApi(memberId, lastWorkspaceId, limit),
|
||||
});
|
||||
};
|
||||
|
||||
export const useCreateWorkspace = (): UseMutationResult<
|
||||
WorkspaceResponse,
|
||||
AxiosError<ErrorResponse>,
|
||||
{ memberId: number; data: { title: string; content: string } }
|
||||
> => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: ({ memberId, data }) => createWorkspaceApi(memberId, data),
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ['workspace'] });
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const useAddWorkspaceMember = (): UseMutationResult<
|
||||
WorkspaceResponse,
|
||||
AxiosError<ErrorResponse>,
|
||||
{ workspaceId: number; memberId: number; newMemberId: number }
|
||||
> => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: ({ workspaceId, memberId, newMemberId }) => addWorkspaceMemberApi(workspaceId, memberId, newMemberId),
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ['workspace'] });
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const useRemoveWorkspaceMember = (): UseMutationResult<
|
||||
WorkspaceResponse,
|
||||
AxiosError<ErrorResponse>,
|
||||
{ workspaceId: number; memberId: number; targetMemberId: number }
|
||||
> => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: ({ workspaceId, memberId, targetMemberId }) =>
|
||||
removeWorkspaceMemberApi(workspaceId, memberId, targetMemberId),
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ['workspace'] });
|
||||
},
|
||||
});
|
||||
};
|
Loading…
Reference in New Issue
Block a user