ERP-node/frontend/hooks/admin/useButtonActions.ts

315 lines
8.5 KiB
TypeScript

"use client";
import { useState, useEffect, useCallback } from "react";
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
// 버튼 액션 데이터 인터페이스
export interface ButtonActionStandard {
action_type: string;
action_name: string;
action_name_eng?: string;
description?: string;
category: string;
default_text?: string;
default_text_eng?: string;
default_icon?: string;
default_color?: string;
default_variant?: string;
confirmation_required: boolean;
confirmation_message?: string;
validation_rules?: any;
action_config?: any;
sort_order?: number;
is_active: string;
created_date?: string;
created_by?: string;
updated_date?: string;
updated_by?: string;
}
// 버튼 액션 생성/수정 데이터
export interface ButtonActionFormData {
action_type: string;
action_name: string;
action_name_eng?: string;
description?: string;
category: string;
default_text?: string;
default_text_eng?: string;
default_icon?: string;
default_color?: string;
default_variant?: string;
confirmation_required?: boolean;
confirmation_message?: string;
validation_rules?: any;
action_config?: any;
sort_order?: number;
is_active?: string;
}
// API 응답 인터페이스
interface ApiResponse<T> {
success: boolean;
data?: T;
message?: string;
error?: string;
}
// 쿼리 파라미터 인터페이스
interface ButtonActionQueryParams {
active?: string;
category?: string;
search?: string;
}
/**
* 버튼 액션 관리 훅
*/
export const useButtonActions = (params?: ButtonActionQueryParams) => {
const queryClient = useQueryClient();
// 버튼 액션 목록 조회
const {
data: buttonActions,
isLoading,
error,
refetch,
} = useQuery({
queryKey: ["buttonActions", params],
queryFn: async (): Promise<ButtonActionStandard[]> => {
const searchParams = new URLSearchParams();
if (params?.active) searchParams.append("active", params.active);
if (params?.category) searchParams.append("category", params.category);
if (params?.search) searchParams.append("search", params.search);
const response = await fetch(
`/api/admin/button-actions?${searchParams.toString()}`,
{
headers: {
Authorization: `Bearer ${localStorage.getItem("token")}`,
"Content-Type": "application/json",
},
}
);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const result: ApiResponse<ButtonActionStandard[]> = await response.json();
if (!result.success) {
throw new Error(result.error || "Failed to fetch button actions");
}
return result.data || [];
},
staleTime: 5 * 60 * 1000, // 5분간 캐시 유지
cacheTime: 10 * 60 * 1000, // 10분간 메모리 보관
});
// 버튼 액션 생성
const createButtonActionMutation = useMutation({
mutationFn: async (
data: ButtonActionFormData
): Promise<ButtonActionStandard> => {
const response = await fetch("/api/admin/button-actions", {
method: "POST",
headers: {
Authorization: `Bearer ${localStorage.getItem("token")}`,
"Content-Type": "application/json",
},
body: JSON.stringify(data),
});
if (!response.ok) {
const errorData = await response.json();
throw new Error(
errorData.message || `HTTP error! status: ${response.status}`
);
}
const result: ApiResponse<ButtonActionStandard> = await response.json();
if (!result.success) {
throw new Error(result.error || "Failed to create button action");
}
return result.data!;
},
onSuccess: () => {
// 목록 새로고침
queryClient.invalidateQueries({ queryKey: ["buttonActions"] });
},
});
// 버튼 액션 수정
const updateButtonActionMutation = useMutation({
mutationFn: async ({
actionType,
data,
}: {
actionType: string;
data: Partial<ButtonActionFormData>;
}): Promise<ButtonActionStandard> => {
const response = await fetch(`/api/admin/button-actions/${actionType}`, {
method: "PUT",
headers: {
Authorization: `Bearer ${localStorage.getItem("token")}`,
"Content-Type": "application/json",
},
body: JSON.stringify(data),
});
if (!response.ok) {
const errorData = await response.json();
throw new Error(
errorData.message || `HTTP error! status: ${response.status}`
);
}
const result: ApiResponse<ButtonActionStandard> = await response.json();
if (!result.success) {
throw new Error(result.error || "Failed to update button action");
}
return result.data!;
},
onSuccess: () => {
// 목록 새로고침
queryClient.invalidateQueries({ queryKey: ["buttonActions"] });
},
});
// 버튼 액션 삭제
const deleteButtonActionMutation = useMutation({
mutationFn: async (actionType: string): Promise<void> => {
const response = await fetch(`/api/admin/button-actions/${actionType}`, {
method: "DELETE",
headers: {
Authorization: `Bearer ${localStorage.getItem("token")}`,
"Content-Type": "application/json",
},
});
if (!response.ok) {
const errorData = await response.json();
throw new Error(
errorData.message || `HTTP error! status: ${response.status}`
);
}
const result: ApiResponse<void> = await response.json();
if (!result.success) {
throw new Error(result.error || "Failed to delete button action");
}
},
onSuccess: () => {
// 목록 새로고침
queryClient.invalidateQueries({ queryKey: ["buttonActions"] });
},
});
// 정렬 순서 업데이트
const updateSortOrderMutation = useMutation({
mutationFn: async (
buttonActions: { action_type: string; sort_order: number }[]
): Promise<void> => {
const response = await fetch(
"/api/admin/button-actions/sort-order/bulk",
{
method: "PUT",
headers: {
Authorization: `Bearer ${localStorage.getItem("token")}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ buttonActions }),
}
);
if (!response.ok) {
const errorData = await response.json();
throw new Error(
errorData.message || `HTTP error! status: ${response.status}`
);
}
const result: ApiResponse<void> = await response.json();
if (!result.success) {
throw new Error(result.error || "Failed to update sort order");
}
},
onSuccess: () => {
// 목록 새로고침
queryClient.invalidateQueries({ queryKey: ["buttonActions"] });
},
});
// 편의 메서드들
const createButtonAction = useCallback(
(data: ButtonActionFormData) => {
return createButtonActionMutation.mutateAsync(data);
},
[createButtonActionMutation]
);
const updateButtonAction = useCallback(
(actionType: string, data: Partial<ButtonActionFormData>) => {
return updateButtonActionMutation.mutateAsync({ actionType, data });
},
[updateButtonActionMutation]
);
const deleteButtonAction = useCallback(
(actionType: string) => {
return deleteButtonActionMutation.mutateAsync(actionType);
},
[deleteButtonActionMutation]
);
const updateSortOrder = useCallback(
(buttonActions: { action_type: string; sort_order: number }[]) => {
return updateSortOrderMutation.mutateAsync(buttonActions);
},
[updateSortOrderMutation]
);
return {
// 데이터
buttonActions: buttonActions || [],
// 로딩 상태
isLoading,
isCreating: createButtonActionMutation.isPending,
isUpdating: updateButtonActionMutation.isPending,
isDeleting: deleteButtonActionMutation.isPending,
isSortingUpdating: updateSortOrderMutation.isPending,
// 에러
error,
createError: createButtonActionMutation.error,
updateError: updateButtonActionMutation.error,
deleteError: deleteButtonActionMutation.error,
sortError: updateSortOrderMutation.error,
// 액션
createButtonAction,
updateButtonAction,
deleteButtonAction,
updateSortOrder,
refetch,
// 상태 초기화
resetCreateError: createButtonActionMutation.reset,
resetUpdateError: updateButtonActionMutation.reset,
resetDeleteError: deleteButtonActionMutation.reset,
resetSortError: updateSortOrderMutation.reset,
};
};