feat(WEB): 회계/HR/주문관리 모듈 개선 및 알림설정 리팩토링

- 회계: 거래처, 매입/매출, 입출금 상세 페이지 개선
- HR: 직원 관리 및 출퇴근 설정 기능 수정
- 주문관리: 상세폼 구조 분리 (cards, dialogs, hooks, tables)
- 알림설정: 컴포넌트 구조 단순화 및 리팩토링
- 캘린더: 헤더 및 일정 타입 개선
- 출고관리: 액션 및 타입 정의 추가

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
byeongcheolryu
2026-01-06 09:58:10 +09:00
parent 386cd30bc0
commit a938da9e22
76 changed files with 2899 additions and 2073 deletions

View File

@@ -40,7 +40,7 @@ import {
PRIORITY_STYLES,
DELIVERY_METHOD_LABELS,
} from './types';
import type { ShipmentItem, ShipmentStatus, ShipmentStats } from './types';
import type { ShipmentItem, ShipmentStatus, ShipmentStats, ShipmentStatusStats } from './types';
// 페이지당 항목 수
const ITEMS_PER_PAGE = 20;
@@ -55,7 +55,7 @@ export function ShipmentList() {
// API 데이터 상태
const [items, setItems] = useState<ShipmentItem[]>([]);
const [shipmentStats, setShipmentStats] = useState<ShipmentStats | null>(null);
const [statusStats, setStatusStats] = useState<Record<string, { label: string; count: number }>>({});
const [statusStats, setStatusStats] = useState<ShipmentStatusStats>({});
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const [totalItems, setTotalItems] = useState(0);

View File

@@ -23,6 +23,7 @@ import type {
ShipmentDetail,
ShipmentProduct,
ShipmentStats,
ShipmentStatusStats,
ShipmentStatus,
ShipmentPriority,
DeliveryMethod,
@@ -184,15 +185,38 @@ function transformApiToDetail(data: ShipmentApiData): ShipmentDetail {
}
// ===== API → Frontend 변환 (통계용) =====
function transformApiToStats(data: ShipmentApiStatsResponse): ShipmentStats {
function transformApiToStats(data: ShipmentApiStatsResponse & { total_count?: number }): ShipmentStats {
return {
todayShipmentCount: data.today_shipment_count,
scheduledCount: data.scheduled_count,
shippingCount: data.shipping_count,
urgentCount: data.urgent_count,
totalCount: data.total_count || 0,
};
}
// ===== API → Frontend 변환 (상태별 통계용) =====
const STATUS_TAB_LABELS: Record<string, string> = {
all: '전체',
scheduled: '출고예정',
ready: '출하대기',
shipping: '배송중',
completed: '배송완료',
};
function transformApiToStatsByStatus(data: ShipmentApiStatsByStatusResponse): ShipmentStatusStats {
const result: ShipmentStatusStats = {};
for (const [key, count] of Object.entries(data)) {
if (key !== 'all') { // all은 탭에서 제외 (전체 탭은 별도 처리)
result[key] = {
label: STATUS_TAB_LABELS[key] || key,
count: count as number,
};
}
}
return result;
}
// ===== Frontend → API 변환 (등록용) =====
function transformCreateFormToApi(
data: ShipmentCreateFormData
@@ -400,7 +424,7 @@ export async function getShipmentStats(): Promise<{
// ===== 상태별 통계 조회 (탭용) =====
export async function getShipmentStatsByStatus(): Promise<{
success: boolean;
data?: ShipmentApiStatsByStatusResponse;
data?: ShipmentStatusStats;
error?: string;
__authError?: boolean;
}> {
@@ -428,7 +452,7 @@ export async function getShipmentStatsByStatus(): Promise<{
return { success: false, error: result.message || '상태별 통계 조회에 실패했습니다.' };
}
return { success: true, data: result.data };
return { success: true, data: transformApiToStatsByStatus(result.data) };
} catch (error) {
console.error('[ShipmentActions] getShipmentStatsByStatus error:', error);
return { success: false, error: '서버 오류가 발생했습니다.' };

View File

@@ -18,6 +18,7 @@ export const mockStats: ShipmentStats = {
scheduledCount: 5,
shippingCount: 1,
urgentCount: 4,
totalCount: 20,
};
// 필터 탭

View File

@@ -156,6 +156,15 @@ export interface ShipmentStats {
scheduledCount: number; // 출고 대기
shippingCount: number; // 배송중
urgentCount: number; // 긴급 출하
totalCount: number; // 전체 건수
}
// 상태별 통계 (탭용)
export interface ShipmentStatusStats {
[key: string]: {
label: string;
count: number;
};
}
// 필터 탭