refactor: UI 컴포넌트 추상화 및 입금/출금 등록 버튼 추가
- 입금관리, 출금관리 리스트에 등록 버튼 추가 - skeleton, confirm-dialog, empty-state, status-badge UI 컴포넌트 추가 - document-system 컴포넌트 추상화 (ApprovalLine, DocumentHeader 등) - 여러 페이지 컴포넌트 리팩토링 및 코드 정리 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
154
src/lib/utils/status-config.ts
Normal file
154
src/lib/utils/status-config.ts
Normal file
@@ -0,0 +1,154 @@
|
||||
/**
|
||||
* 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;
|
||||
Reference in New Issue
Block a user