- 입금관리, 출금관리 리스트에 등록 버튼 추가 - skeleton, confirm-dialog, empty-state, status-badge UI 컴포넌트 추가 - document-system 컴포넌트 추상화 (ApprovalLine, DocumentHeader 등) - 여러 페이지 컴포넌트 리팩토링 및 코드 정리 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
155 lines
4.7 KiB
TypeScript
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;
|