refactor(WEB): 전체 actions.ts에 공통 API 유틸 적용
- buildApiUrl / executePaginatedAction 패턴으로 전환 (40+ actions 파일) - 직접 URLSearchParams 조립 → buildApiUrl 유틸 사용 - 수동 페이지네이션 메타 변환 → executePaginatedAction 자동 처리 - HandoverReportDocumentModal, OrderDocumentModal 개선 - 급여관리 SalaryManagement 코드 개선 - CLAUDE.md Server Action 공통 유틸 규칙 정리 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
|
||||
|
||||
import { executeServerAction } from '@/lib/api/execute-server-action';
|
||||
import { buildApiUrl } from '@/lib/api/query-params';
|
||||
import type { PaginatedApiResponse } from '@/lib/api/types';
|
||||
import { isNextRedirectError } from '@/lib/utils/redirect-error';
|
||||
import { cookies } from 'next/headers';
|
||||
@@ -44,18 +45,17 @@ export async function getEmployees(params?: {
|
||||
department_id?: string; has_account?: boolean;
|
||||
sort_by?: string; sort_dir?: 'asc' | 'desc';
|
||||
}): Promise<{ data: Employee[]; total: number; lastPage: number; __authError?: boolean }> {
|
||||
const searchParams = new URLSearchParams();
|
||||
if (params?.page) searchParams.set('page', String(params.page));
|
||||
if (params?.per_page) searchParams.set('per_page', String(params.per_page));
|
||||
if (params?.q) searchParams.set('q', params.q);
|
||||
if (params?.status && params.status !== 'all') searchParams.set('status', params.status);
|
||||
if (params?.department_id) searchParams.set('department_id', params.department_id);
|
||||
if (params?.has_account !== undefined) searchParams.set('has_account', String(params.has_account));
|
||||
if (params?.sort_by) searchParams.set('sort_by', params.sort_by);
|
||||
if (params?.sort_dir) searchParams.set('sort_dir', params.sort_dir);
|
||||
|
||||
const result = await executeServerAction<PaginatedApiResponse<EmployeeApiData>>({
|
||||
url: `${API_URL}/api/v1/employees?${searchParams.toString()}`,
|
||||
url: buildApiUrl('/api/v1/employees', {
|
||||
page: params?.page,
|
||||
per_page: params?.per_page,
|
||||
q: params?.q,
|
||||
status: params?.status && params.status !== 'all' ? params.status : undefined,
|
||||
department_id: params?.department_id,
|
||||
has_account: params?.has_account,
|
||||
sort_by: params?.sort_by,
|
||||
sort_dir: params?.sort_dir,
|
||||
}),
|
||||
errorMessage: '직원 목록 조회에 실패했습니다.',
|
||||
});
|
||||
|
||||
@@ -71,7 +71,7 @@ export async function getEmployees(params?: {
|
||||
|
||||
export async function getEmployeeById(id: string): Promise<Employee | null | { __authError: true }> {
|
||||
const result = await executeServerAction({
|
||||
url: `${API_URL}/api/v1/employees/${id}`,
|
||||
url: buildApiUrl(`/api/v1/employees/${id}`),
|
||||
transform: (data: EmployeeApiData) => transformApiToFrontend(data),
|
||||
errorMessage: '직원 조회에 실패했습니다.',
|
||||
});
|
||||
@@ -88,7 +88,7 @@ export async function createEmployee(
|
||||
}> {
|
||||
const apiData = transformFrontendToApi(data);
|
||||
const result = await executeServerAction({
|
||||
url: `${API_URL}/api/v1/employees`,
|
||||
url: buildApiUrl('/api/v1/employees'),
|
||||
method: 'POST',
|
||||
body: apiData,
|
||||
transform: (d: EmployeeApiData) => transformApiToFrontend(d),
|
||||
@@ -105,7 +105,7 @@ export async function updateEmployee(
|
||||
): Promise<{ success: boolean; data?: Employee; error?: string; __authError?: boolean }> {
|
||||
const apiData = transformFrontendToApi(data);
|
||||
const result = await executeServerAction({
|
||||
url: `${API_URL}/api/v1/employees/${id}`,
|
||||
url: buildApiUrl(`/api/v1/employees/${id}`),
|
||||
method: 'PATCH',
|
||||
body: apiData,
|
||||
transform: (d: EmployeeApiData) => transformApiToFrontend(d),
|
||||
@@ -118,7 +118,7 @@ export async function updateEmployee(
|
||||
|
||||
export async function deleteEmployee(id: string): Promise<{ success: boolean; error?: string; __authError?: boolean }> {
|
||||
const result = await executeServerAction({
|
||||
url: `${API_URL}/api/v1/employees/${id}`,
|
||||
url: buildApiUrl(`/api/v1/employees/${id}`),
|
||||
method: 'DELETE',
|
||||
errorMessage: '직원 삭제에 실패했습니다.',
|
||||
});
|
||||
@@ -129,7 +129,7 @@ export async function deleteEmployee(id: string): Promise<{ success: boolean; er
|
||||
|
||||
export async function deleteEmployees(ids: string[]): Promise<{ success: boolean; error?: string; __authError?: boolean }> {
|
||||
const result = await executeServerAction({
|
||||
url: `${API_URL}/api/v1/employees/bulk-delete`,
|
||||
url: buildApiUrl('/api/v1/employees/bulk-delete'),
|
||||
method: 'POST',
|
||||
body: { ids: ids.map(id => parseInt(id, 10)) },
|
||||
errorMessage: '직원 일괄 삭제에 실패했습니다.',
|
||||
@@ -148,7 +148,7 @@ interface EmployeeStatsApiData {
|
||||
|
||||
export async function getEmployeeStats(): Promise<EmployeeStats | null | { __authError: true }> {
|
||||
const result = await executeServerAction<EmployeeStatsApiData>({
|
||||
url: `${API_URL}/api/v1/employees/stats`,
|
||||
url: buildApiUrl('/api/v1/employees/stats'),
|
||||
errorMessage: '직원 통계 조회에 실패했습니다.',
|
||||
});
|
||||
|
||||
@@ -177,11 +177,10 @@ export interface PositionItem {
|
||||
}
|
||||
|
||||
export async function getPositions(type?: 'rank' | 'title'): Promise<PositionItem[]> {
|
||||
const searchParams = new URLSearchParams();
|
||||
if (type) searchParams.set('type', type);
|
||||
|
||||
const result = await executeServerAction<PositionItem[]>({
|
||||
url: `${API_URL}/api/v1/positions?${searchParams.toString()}`,
|
||||
url: buildApiUrl('/api/v1/positions', {
|
||||
type,
|
||||
}),
|
||||
errorMessage: '직급/직책 조회에 실패했습니다.',
|
||||
});
|
||||
return result.data || [];
|
||||
@@ -201,7 +200,7 @@ export interface DepartmentItem {
|
||||
|
||||
export async function getDepartments(): Promise<DepartmentItem[]> {
|
||||
const result = await executeServerAction<DepartmentItem[] | { data: DepartmentItem[] }>({
|
||||
url: `${API_URL}/api/v1/departments`,
|
||||
url: buildApiUrl('/api/v1/departments'),
|
||||
errorMessage: '부서 조회에 실패했습니다.',
|
||||
});
|
||||
if (!result.data) return [];
|
||||
|
||||
Reference in New Issue
Block a user