Files
sam-react-prod/src/lib/utils/status-config.ts
유병철 269b901e64 refactor: UI 컴포넌트 추상화 및 입금/출금 등록 버튼 추가
- 입금관리, 출금관리 리스트에 등록 버튼 추가
- skeleton, confirm-dialog, empty-state, status-badge UI 컴포넌트 추가
- document-system 컴포넌트 추상화 (ApprovalLine, DocumentHeader 등)
- 여러 페이지 컴포넌트 리팩토링 및 코드 정리

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 17:21:42 +09:00

155 lines
4.7 KiB
TypeScript

/**
* Status Configuration Utility
*
* 상태 관련 설정(OPTIONS, LABELS, STYLES)을 단일 설정에서 생성하는 유틸리티
*
* 사용 예시:
* ```ts
* const { STATUS_OPTIONS, STATUS_LABELS, STATUS_STYLES, getStatusLabel, getStatusStyle } =
* createStatusConfig({
* pending: { label: '대기', style: 'warning' },
* completed: { label: '완료', style: 'success' },
* rejected: { label: '반려', style: 'destructive' },
* }, { includeAll: true, allLabel: '전체' });
* ```
*/
// 프리셋 스타일 정의
export type StatusStylePreset =
| 'default'
| 'success'
| 'warning'
| 'destructive'
| 'info'
| 'muted'
| 'orange'
| 'purple';
// 프리셋 스타일 맵 (Badge 스타일 - 배경 + 텍스트)
export const BADGE_STYLE_PRESETS: Record<StatusStylePreset, string> = {
default: 'bg-gray-100 text-gray-800',
success: 'bg-green-100 text-green-800',
warning: 'bg-yellow-100 text-yellow-800',
destructive: 'bg-red-100 text-red-800',
info: 'bg-blue-100 text-blue-800',
muted: 'bg-gray-100 text-gray-500',
orange: 'bg-orange-100 text-orange-800',
purple: 'bg-purple-100 text-purple-800',
};
// 프리셋 스타일 맵 (Text 스타일 - 텍스트만)
export const TEXT_STYLE_PRESETS: Record<StatusStylePreset, string> = {
default: 'text-gray-600 font-medium',
success: 'text-green-600 font-medium',
warning: 'text-yellow-600 font-medium',
destructive: 'text-red-500 font-medium',
info: 'text-blue-500 font-medium',
muted: 'text-gray-400 font-medium',
orange: 'text-orange-500 font-medium',
purple: 'text-purple-500 font-medium',
};
// 단일 상태 설정 타입
export interface StatusItemConfig {
/** 표시 라벨 */
label: string;
/** 프리셋 스타일 또는 커스텀 클래스 */
style: StatusStylePreset | string;
}
// createStatusConfig 옵션
export interface CreateStatusConfigOptions {
/** '전체' 옵션 포함 여부 (기본값: false) */
includeAll?: boolean;
/** '전체' 옵션 라벨 (기본값: '전체') */
allLabel?: string;
/** 스타일 모드: 'badge' (배경+텍스트) 또는 'text' (텍스트만) */
styleMode?: 'badge' | 'text';
}
// 반환 타입
export interface StatusConfig<T extends string> {
/** Select 컴포넌트용 옵션 배열 */
STATUS_OPTIONS: ReadonlyArray<{ value: T | 'all'; label: string }>;
/** 상태별 라벨 맵 */
STATUS_LABELS: Record<T, string>;
/** 상태별 스타일 맵 */
STATUS_STYLES: Record<T, string>;
/** 상태값으로 라벨 가져오기 */
getStatusLabel: (status: T) => string;
/** 상태값으로 스타일 가져오기 */
getStatusStyle: (status: T) => string;
}
/**
* 상태 설정 생성 유틸리티
*
* @param config - 상태별 설정 객체
* @param options - 추가 옵션
* @returns STATUS_OPTIONS, STATUS_LABELS, STATUS_STYLES 및 헬퍼 함수
*/
export function createStatusConfig<T extends string>(
config: Record<T, StatusItemConfig>,
options: CreateStatusConfigOptions = {}
): StatusConfig<T> {
const { includeAll = false, allLabel = '전체', styleMode = 'badge' } = options;
const stylePresets = styleMode === 'badge' ? BADGE_STYLE_PRESETS : TEXT_STYLE_PRESETS;
// STATUS_LABELS 생성
const STATUS_LABELS = Object.entries(config).reduce(
(acc, [key, value]) => {
acc[key as T] = (value as StatusItemConfig).label;
return acc;
},
{} as Record<T, string>
);
// STATUS_STYLES 생성
const STATUS_STYLES = Object.entries(config).reduce(
(acc, [key, value]) => {
const { style } = value as StatusItemConfig;
// 프리셋 스타일이면 변환, 아니면 커스텀 클래스 그대로 사용
acc[key as T] =
style in stylePresets ? stylePresets[style as StatusStylePreset] : style;
return acc;
},
{} as Record<T, string>
);
// STATUS_OPTIONS 생성
const statusOptions = Object.entries(config).map(([key, value]) => ({
value: key as T,
label: (value as StatusItemConfig).label,
}));
const STATUS_OPTIONS = includeAll
? [{ value: 'all' as const, label: allLabel }, ...statusOptions]
: statusOptions;
// 헬퍼 함수
const getStatusLabel = (status: T): string => STATUS_LABELS[status] || status;
const getStatusStyle = (status: T): string => STATUS_STYLES[status] || '';
return {
STATUS_OPTIONS: STATUS_OPTIONS as ReadonlyArray<{ value: T | 'all'; label: string }>,
STATUS_LABELS,
STATUS_STYLES,
getStatusLabel,
getStatusStyle,
};
}
/**
* 프리셋 스타일을 CSS 클래스로 변환하는 헬퍼
*/
export function getPresetStyle(
preset: StatusStylePreset,
mode: 'badge' | 'text' = 'badge'
): string {
const presets = mode === 'badge' ? BADGE_STYLE_PRESETS : TEXT_STYLE_PRESETS;
return presets[preset] || presets.default;
}
export default createStatusConfig;