Feat: get method API 쿼리 함수 추가
This commit is contained in:
parent
07eadc03f6
commit
503976b3ee
@ -1,11 +1,14 @@
|
||||
import api from '@/api/axiosConfig';
|
||||
import { MemberResponse, RefreshTokenResponse } from '@/types';
|
||||
|
||||
export async function reissueToken() {
|
||||
return api.post('/auth/reissue', null, { withCredentials: true });
|
||||
return api.post<RefreshTokenResponse>('/auth/reissue', null, { withCredentials: true }).then(({ data }) => data);
|
||||
}
|
||||
|
||||
export async function fetchProfile() {
|
||||
return api.get('/auth/profile', {
|
||||
withCredentials: true,
|
||||
});
|
||||
export async function getProfile() {
|
||||
return api
|
||||
.get<MemberResponse>('/auth/profile', {
|
||||
withCredentials: true,
|
||||
})
|
||||
.then(({ data }) => data);
|
||||
}
|
||||
|
@ -1,37 +1,42 @@
|
||||
import api from '@/api/axiosConfig';
|
||||
import { FolderRequestDTO } from '@/types';
|
||||
import { FolderRequest, FolderResponse } from '@/types';
|
||||
|
||||
export async function fetchFolder(projectId: number, folderId: number, memberId: number) {
|
||||
return api.get(`/projects/${projectId}/folders/${folderId}`, {
|
||||
params: { memberId },
|
||||
});
|
||||
return api
|
||||
.get<FolderResponse>(`/projects/${projectId}/folders/${folderId}`, {
|
||||
params: { memberId },
|
||||
})
|
||||
.then(({ data }) => data);
|
||||
}
|
||||
|
||||
export async function updateFolder(
|
||||
projectId: number,
|
||||
folderId: number,
|
||||
memberId: number,
|
||||
folderData: FolderRequestDTO
|
||||
) {
|
||||
return api.put(`/projects/${projectId}/folders/${folderId}`, folderData, {
|
||||
params: { memberId },
|
||||
});
|
||||
export async function updateFolder(projectId: number, folderId: number, memberId: number, folderData: FolderRequest) {
|
||||
return api
|
||||
.put(`/projects/${projectId}/folders/${folderId}`, folderData, {
|
||||
params: { memberId },
|
||||
})
|
||||
.then(({ data }) => data);
|
||||
}
|
||||
|
||||
export async function deleteFolder(projectId: number, folderId: number, memberId: number) {
|
||||
return api.delete(`/projects/${projectId}/folders/${folderId}`, {
|
||||
params: { memberId },
|
||||
});
|
||||
return api
|
||||
.delete(`/projects/${projectId}/folders/${folderId}`, {
|
||||
params: { memberId },
|
||||
})
|
||||
.then(({ data }) => data);
|
||||
}
|
||||
|
||||
export async function createFolder(projectId: number, memberId: number, folderData: FolderRequestDTO) {
|
||||
return api.post(`/projects/${projectId}/folders`, folderData, {
|
||||
params: { memberId },
|
||||
});
|
||||
export async function createFolder(projectId: number, memberId: number, folderData: FolderRequest) {
|
||||
return api
|
||||
.post(`/projects/${projectId}/folders`, folderData, {
|
||||
params: { memberId },
|
||||
})
|
||||
.then(({ data }) => data);
|
||||
}
|
||||
|
||||
export async function fetchFolderReviewList(projectId: number, folderId: number, memberId: number) {
|
||||
return api.get(`/projects/${projectId}/folders/${folderId}/review`, {
|
||||
params: { memberId },
|
||||
});
|
||||
export async function getFolderReviewList(projectId: number, folderId: number, memberId: number) {
|
||||
return api
|
||||
.get(`/projects/${projectId}/folders/${folderId}/review`, {
|
||||
params: { memberId },
|
||||
})
|
||||
.then(({ data }) => data);
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import api from '@/api/axiosConfig';
|
||||
import { ImageMoveRequestDTO, ImageStatusChangeRequestDTO } from '@/types';
|
||||
import { ImageMoveRequest, ImageStatusChangeRequest } from '@/types';
|
||||
|
||||
export async function fetchImage(projectId: number, folderId: number, imageId: number, memberId: number) {
|
||||
export async function getImage(projectId: number, folderId: number, imageId: number, memberId: number) {
|
||||
return api.get(`/projects/${projectId}/folders/${folderId}/images/${imageId}`, {
|
||||
params: { memberId },
|
||||
});
|
||||
@ -12,7 +12,7 @@ export async function moveImage(
|
||||
folderId: number,
|
||||
imageId: number,
|
||||
memberId: number,
|
||||
moveRequest: ImageMoveRequestDTO
|
||||
moveRequest: ImageMoveRequest
|
||||
) {
|
||||
return api.put(`/projects/${projectId}/folders/${folderId}/images/${imageId}`, moveRequest, {
|
||||
params: { memberId },
|
||||
@ -30,7 +30,7 @@ export async function changeImageStatus(
|
||||
folderId: number,
|
||||
imageId: number,
|
||||
memberId: number,
|
||||
statusChangeRequest: ImageStatusChangeRequestDTO
|
||||
statusChangeRequest: ImageStatusChangeRequest
|
||||
) {
|
||||
return api.put(`/projects/${projectId}/folders/${folderId}/images/${imageId}/status`, statusChangeRequest, {
|
||||
params: { memberId },
|
||||
|
@ -1,7 +1,7 @@
|
||||
import api from '@/api/axiosConfig';
|
||||
import { LabelingRequestDTO } from '@/types';
|
||||
import { LabelingRequest } from '@/types';
|
||||
|
||||
export async function saveImageLabels(projectId: number, imageId: number, memberId: number, data: LabelingRequestDTO) {
|
||||
export async function saveImageLabels(projectId: number, imageId: number, memberId: number, data: LabelingRequest) {
|
||||
return api.post(`/projects/${projectId}/label/image/${imageId}`, data, {
|
||||
params: { memberId },
|
||||
});
|
||||
|
@ -1,70 +1,84 @@
|
||||
import api from '@/api/axiosConfig';
|
||||
|
||||
export async function getProjectApi(projectId: number, memberId: number) {
|
||||
return api.get(`/projects/${projectId}`, {
|
||||
params: { memberId },
|
||||
});
|
||||
export async function getProject(projectId: number, memberId: number) {
|
||||
return api
|
||||
.get(`/projects/${projectId}`, {
|
||||
params: { memberId },
|
||||
})
|
||||
.then(({ data }) => data);
|
||||
}
|
||||
|
||||
export async function updateProjectApi(
|
||||
export async function updateProject(
|
||||
projectId: number,
|
||||
memberId: number,
|
||||
data: { title: string; projectType: 'classification' | 'detection' | 'segmentation' }
|
||||
) {
|
||||
return api.put(`/projects/${projectId}`, data, {
|
||||
params: { memberId },
|
||||
});
|
||||
return api
|
||||
.put(`/projects/${projectId}`, data, {
|
||||
params: { memberId },
|
||||
})
|
||||
.then(({ data }) => data);
|
||||
}
|
||||
|
||||
export async function deleteProjectApi(projectId: number, memberId: number) {
|
||||
return api.delete(`/projects/${projectId}`, {
|
||||
params: { memberId },
|
||||
});
|
||||
export async function deleteProject(projectId: number, memberId: number) {
|
||||
return api
|
||||
.delete(`/projects/${projectId}`, {
|
||||
params: { memberId },
|
||||
})
|
||||
.then(({ data }) => data);
|
||||
}
|
||||
|
||||
export async function addProjectMemberApi(
|
||||
export async function addProjectMember(
|
||||
projectId: number,
|
||||
memberId: number,
|
||||
newMemberId: number,
|
||||
privilegeType: string
|
||||
) {
|
||||
return api.post(
|
||||
`/projects/${projectId}/members`,
|
||||
{ memberId: newMemberId, privilegeType },
|
||||
{
|
||||
return api
|
||||
.post(
|
||||
`/projects/${projectId}/members`,
|
||||
{ memberId: newMemberId, privilegeType },
|
||||
{
|
||||
params: { memberId },
|
||||
}
|
||||
)
|
||||
.then(({ data }) => data);
|
||||
}
|
||||
|
||||
export async function removeProjectMember(projectId: number, memberId: number, targetMemberId: number) {
|
||||
return api
|
||||
.delete(`/projects/${projectId}/members`, {
|
||||
params: { memberId },
|
||||
}
|
||||
);
|
||||
data: { memberId: targetMemberId },
|
||||
})
|
||||
.then(({ data }) => data);
|
||||
}
|
||||
|
||||
export async function removeProjectMemberApi(projectId: number, memberId: number, targetMemberId: number) {
|
||||
return api.delete(`/projects/${projectId}/members`, {
|
||||
params: { memberId },
|
||||
data: { memberId: targetMemberId },
|
||||
});
|
||||
}
|
||||
|
||||
export async function getAllProjectsApi(
|
||||
export async function getAllProjects(
|
||||
workspaceId: number,
|
||||
memberId: number,
|
||||
lastProjectId?: number,
|
||||
limit: number = 10
|
||||
) {
|
||||
return api.get(`/workspaces/${workspaceId}/projects`, {
|
||||
params: {
|
||||
memberId,
|
||||
lastProjectId,
|
||||
limit,
|
||||
},
|
||||
});
|
||||
return api
|
||||
.get(`/workspaces/${workspaceId}/projects`, {
|
||||
params: {
|
||||
memberId,
|
||||
lastProjectId,
|
||||
limit,
|
||||
},
|
||||
})
|
||||
.then(({ data }) => data);
|
||||
}
|
||||
|
||||
export async function createProjectApi(
|
||||
export async function createProject(
|
||||
workspaceId: number,
|
||||
memberId: number,
|
||||
data: { title: string; projectType: 'classification' | 'detection' | 'segmentation' }
|
||||
) {
|
||||
return api.post(`/workspaces/${workspaceId}/projects`, data, {
|
||||
params: { memberId },
|
||||
});
|
||||
return api
|
||||
.post(`/workspaces/${workspaceId}/projects`, data, {
|
||||
params: { memberId },
|
||||
})
|
||||
.then(({ data }) => data);
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ export async function uploadFilesToProject(
|
||||
formData.append('files', file);
|
||||
});
|
||||
|
||||
// TODO: api.post()를 return하고 사이드 이펙트는 외부에서 처리하도록 수정
|
||||
return api
|
||||
.post('/projects/{project_id}', formData, {
|
||||
onUploadProgress: (progressEvent: AxiosProgressEvent) => {
|
||||
|
@ -1,5 +1,5 @@
|
||||
import api from '@/api/axiosConfig';
|
||||
import { WorkspaceRequestDTO } from '@/types';
|
||||
import { WorkspaceRequest } from '@/types';
|
||||
|
||||
export async function fetchWorkspaceList(memberId: number, lastWorkspaceId?: number, limit?: number) {
|
||||
return api.get('/workspaces', {
|
||||
@ -13,7 +13,7 @@ export async function fetchWorkspace(workspaceId: number, memberId: number) {
|
||||
});
|
||||
}
|
||||
|
||||
export async function updateWorkspace(workspaceId: number, memberId: number, data: WorkspaceRequestDTO) {
|
||||
export async function updateWorkspace(workspaceId: number, memberId: number, data: WorkspaceRequest) {
|
||||
return api.put(`/workspaces/${workspaceId}`, data, {
|
||||
params: { memberId },
|
||||
});
|
||||
@ -25,7 +25,7 @@ export async function deleteWorkspace(workspaceId: number, memberId: number) {
|
||||
});
|
||||
}
|
||||
|
||||
export async function createWorkspace(memberId: number, data: WorkspaceRequestDTO) {
|
||||
export async function createWorkspace(memberId: number, data: WorkspaceRequest) {
|
||||
return api.post('/workspaces', data, {
|
||||
params: { memberId },
|
||||
});
|
||||
|
@ -1,47 +1,31 @@
|
||||
import { useQuery, UseQueryResult, useMutation, useQueryClient, UseMutationResult } from '@tanstack/react-query';
|
||||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import { AxiosError } from 'axios';
|
||||
import useAuthStore from '@/stores/useAuthStore';
|
||||
import { reissueTokenApi, fetchProfileApi } from '@/api/authApi';
|
||||
import { SuccessResponse, RefreshTokenResponseDTO, MemberResponseDTO, CustomError } from '@/types';
|
||||
import { reissueToken, getProfile } from '@/api/authApi';
|
||||
import { CustomError } from '@/types';
|
||||
import { useState, useEffect } from 'react';
|
||||
import useProfileQuery from '@/queries/useProfileQuery';
|
||||
|
||||
export const useReissueToken = (): UseMutationResult<
|
||||
SuccessResponse<RefreshTokenResponseDTO>,
|
||||
AxiosError<CustomError>
|
||||
> => {
|
||||
export const useReissueToken = () => {
|
||||
const queryClient = useQueryClient();
|
||||
const { setLoggedIn } = useAuthStore();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: reissueTokenApi,
|
||||
mutationFn: reissueToken,
|
||||
onSuccess: (data) => {
|
||||
if (data.isSuccess && data.data) {
|
||||
setLoggedIn(true, data.data.accessToken);
|
||||
queryClient.invalidateQueries({ queryKey: ['profile'] });
|
||||
} else {
|
||||
console.error('토큰 재발급 응답 오류:', data.message);
|
||||
}
|
||||
},
|
||||
onError: (error) => {
|
||||
console.error('토큰 재발급 실패:', error?.response?.data?.message || '알 수 없는 오류');
|
||||
setLoggedIn(true, data.accessToken);
|
||||
queryClient.invalidateQueries({ queryKey: ['profile'] });
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const useProfile = (): UseQueryResult<SuccessResponse<MemberResponseDTO>, AxiosError<CustomError>> => {
|
||||
const { accessToken, setProfile } = useAuthStore();
|
||||
|
||||
const query = useQuery<SuccessResponse<MemberResponseDTO>, AxiosError<CustomError>>({
|
||||
queryKey: ['profile'],
|
||||
queryFn: fetchProfileApi,
|
||||
enabled: !!accessToken,
|
||||
select: (data) => data,
|
||||
});
|
||||
export const useProfile = () => {
|
||||
const { setProfile } = useAuthStore();
|
||||
const query = useProfileQuery();
|
||||
|
||||
// TODO: query.data가 변경될 때마다 setProfile을 호출하여 profile 업데이트, useEffect 제거
|
||||
useEffect(() => {
|
||||
if (query.data?.isSuccess) {
|
||||
setProfile(query.data.data);
|
||||
}
|
||||
setProfile(query.data);
|
||||
}, [query.data, setProfile]);
|
||||
|
||||
return query;
|
||||
@ -53,14 +37,10 @@ export const useFetchProfile = () => {
|
||||
|
||||
useEffect(() => {
|
||||
if (!profile && !isFetched) {
|
||||
fetchProfileApi()
|
||||
getProfile()
|
||||
.then((data) => {
|
||||
if (data.isSuccess && data.data) {
|
||||
setProfile(data.data);
|
||||
setIsFetched(true);
|
||||
} else {
|
||||
console.error('프로필 응답 오류:', data.message);
|
||||
}
|
||||
setProfile(data);
|
||||
setIsFetched(true);
|
||||
})
|
||||
.catch((error: AxiosError<CustomError>) => {
|
||||
alert('프로필을 가져오는 중 오류가 발생했습니다. 다시 시도해주세요.');
|
||||
|
9
frontend/src/queries/useFolderQuery.ts
Normal file
9
frontend/src/queries/useFolderQuery.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { fetchFolder } from '@/api/folderApi';
|
||||
import { useSuspenseQuery } from '@tanstack/react-query';
|
||||
|
||||
export default function useFolderQuery(projectId: number, folderId: number, memberId: number) {
|
||||
return useSuspenseQuery({
|
||||
queryKey: ['folder', projectId, folderId, memberId],
|
||||
queryFn: () => fetchFolder(projectId, folderId, memberId),
|
||||
});
|
||||
}
|
9
frontend/src/queries/useFolderReviewListQuery.ts
Normal file
9
frontend/src/queries/useFolderReviewListQuery.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { getFolderReviewList } from '@/api/folderApi';
|
||||
import { useSuspenseQuery } from '@tanstack/react-query';
|
||||
|
||||
export function useFolderReviewListQuery(projectId: number, folderId: number, memberId: number) {
|
||||
return useSuspenseQuery({
|
||||
queryKey: ['folderReviewList', projectId, folderId, memberId],
|
||||
queryFn: () => getFolderReviewList(projectId, folderId, memberId),
|
||||
});
|
||||
}
|
9
frontend/src/queries/useProfileQuery.ts
Normal file
9
frontend/src/queries/useProfileQuery.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { getProfile } from '@/api/authApi';
|
||||
import { useSuspenseQuery } from '@tanstack/react-query';
|
||||
|
||||
export default function useProfileQuery() {
|
||||
return useSuspenseQuery({
|
||||
queryKey: ['profile'],
|
||||
queryFn: getProfile,
|
||||
});
|
||||
}
|
9
frontend/src/queries/useProjectQuery.ts
Normal file
9
frontend/src/queries/useProjectQuery.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { getProject } from '@/api/projectApi';
|
||||
import { useSuspenseQuery } from '@tanstack/react-query';
|
||||
|
||||
export default function useProjectQuery(projectId: number, memberId: number) {
|
||||
return useSuspenseQuery({
|
||||
queryKey: ['project', projectId, memberId],
|
||||
queryFn: () => getProject(projectId, memberId),
|
||||
});
|
||||
}
|
9
frontend/src/queries/useWorkspaceListQuery.ts
Normal file
9
frontend/src/queries/useWorkspaceListQuery.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { fetchWorkspaceList } from '@/api/workspaceApi';
|
||||
import { useSuspenseQuery } from '@tanstack/react-query';
|
||||
|
||||
export default function useWorkspaceListQuery(memberId: number, lastWorkspaceId?: number, limit?: number) {
|
||||
return useSuspenseQuery({
|
||||
queryKey: ['workspaceList'],
|
||||
queryFn: () => fetchWorkspaceList(memberId, lastWorkspaceId, limit),
|
||||
});
|
||||
}
|
9
frontend/src/queries/useWorkspaceQuery.ts
Normal file
9
frontend/src/queries/useWorkspaceQuery.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { fetchWorkspace } from '@/api/workspaceApi';
|
||||
import { useSuspenseQuery } from '@tanstack/react-query';
|
||||
|
||||
export default function useWorkspaceQuery(workspaceId: number, memberId: number) {
|
||||
return useSuspenseQuery({
|
||||
queryKey: ['workspace', workspaceId, memberId],
|
||||
queryFn: () => fetchWorkspace(workspaceId, memberId),
|
||||
});
|
||||
}
|
@ -34,50 +34,50 @@ export type Label = {
|
||||
coordinates: Array<[number, number]>;
|
||||
};
|
||||
|
||||
export interface FolderRequestDTO {
|
||||
export interface FolderRequest {
|
||||
title: string;
|
||||
parentId: number;
|
||||
}
|
||||
|
||||
export interface ChildFolderDTO {
|
||||
export interface ChildFolder {
|
||||
id: number;
|
||||
title: string;
|
||||
}
|
||||
|
||||
export interface FolderResponseDTO {
|
||||
export interface FolderResponse {
|
||||
id: number;
|
||||
title: string;
|
||||
images: ImageResponseDTO[];
|
||||
children: ChildFolderDTO[];
|
||||
images: ImageResponse[];
|
||||
children: ChildFolder[];
|
||||
}
|
||||
|
||||
export interface ImageResponseDTO {
|
||||
export interface ImageResponse {
|
||||
id: number;
|
||||
imageTitle: string;
|
||||
imageUrl: string;
|
||||
status: 'PENDING' | 'IN_PROGRESS' | 'NEED_REVIEW' | 'COMPLETED';
|
||||
}
|
||||
|
||||
export interface ImageMoveRequestDTO {
|
||||
export interface ImageMoveRequest {
|
||||
moveFolderId: number;
|
||||
}
|
||||
|
||||
export interface ImageStatusChangeRequestDTO {
|
||||
export interface ImageStatusChangeRequest {
|
||||
labelStatus: 'PENDING' | 'IN_PROGRESS' | 'NEED_REVIEW' | 'COMPLETED';
|
||||
}
|
||||
|
||||
export interface MemberResponseDTO {
|
||||
export interface MemberResponse {
|
||||
id: number;
|
||||
nickname: string;
|
||||
profileImage: string;
|
||||
}
|
||||
|
||||
export interface WorkspaceRequestDTO {
|
||||
export interface WorkspaceRequest {
|
||||
title: string;
|
||||
content: string;
|
||||
}
|
||||
|
||||
export interface WorkspaceResponseDTO {
|
||||
export interface WorkspaceResponse {
|
||||
id: number;
|
||||
memberId: string;
|
||||
title: string;
|
||||
@ -86,8 +86,8 @@ export interface WorkspaceResponseDTO {
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface WorkspaceListResponseDTO {
|
||||
workspaceResponses: WorkspaceResponseDTO[];
|
||||
export interface WorkspaceListResponse {
|
||||
workspaceResponses: WorkspaceResponse[];
|
||||
}
|
||||
|
||||
export interface SuccessResponse<T> {
|
||||
@ -98,11 +98,13 @@ export interface SuccessResponse<T> {
|
||||
errors: CustomError[];
|
||||
isSuccess: boolean;
|
||||
}
|
||||
export interface ProjectRequestDTO {
|
||||
|
||||
export interface ProjectRequest {
|
||||
title: string;
|
||||
projectType: 'classification' | 'detection' | 'segmentation';
|
||||
}
|
||||
export interface ProjectResponseDTO {
|
||||
|
||||
export interface ProjectResponse {
|
||||
id: number;
|
||||
title: string;
|
||||
workspaceId: number;
|
||||
@ -111,8 +113,8 @@ export interface ProjectResponseDTO {
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface ProjectListResponseDTO {
|
||||
workspaceResponses: ProjectResponseDTO[];
|
||||
export interface ProjectListResponse {
|
||||
workspaceResponses: ProjectResponse[];
|
||||
}
|
||||
|
||||
export interface CustomError {
|
||||
@ -140,17 +142,17 @@ export interface BaseResponse<T> {
|
||||
isSuccess: boolean;
|
||||
}
|
||||
|
||||
export interface RefreshTokenResponseDTO {
|
||||
export interface RefreshTokenResponse {
|
||||
accessToken: string;
|
||||
}
|
||||
|
||||
export interface CommentRequestDTO {
|
||||
export interface CommentRequest {
|
||||
content: string;
|
||||
positionX: number;
|
||||
positionY: number;
|
||||
}
|
||||
|
||||
export interface CommentResponseDTO {
|
||||
export interface CommentResponse {
|
||||
id: number;
|
||||
memberId: number;
|
||||
memberNickname: string;
|
||||
@ -161,18 +163,18 @@ export interface CommentResponseDTO {
|
||||
createTime: string; // 작성 일자 (ISO 8601 형식)
|
||||
}
|
||||
|
||||
export interface ProjectMemberRequestDTO {
|
||||
export interface ProjectMemberRequest {
|
||||
memberId: number;
|
||||
privilegeType: 'ADMIN' | 'MANAGER' | 'EDITOR' | 'VIEWER';
|
||||
}
|
||||
|
||||
export interface LabelingRequestDTO {
|
||||
export interface LabelingRequest {
|
||||
memberId: number;
|
||||
projectId: number;
|
||||
imageId: number;
|
||||
}
|
||||
|
||||
export interface AutoLabelingResponseDTO {
|
||||
export interface AutoLabelingResponse {
|
||||
imageId: number;
|
||||
imageUrl: string;
|
||||
data: string;
|
||||
|
Loading…
Reference in New Issue
Block a user