"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 { 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 => { 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 = 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 => { 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 = 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; }): Promise => { 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 = 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 => { 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 = 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 => { 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 = 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) => { 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, }; };