- cn() 유틸 신규 (clsx + tailwind-merge, 시맨틱 토큰 classGroup 등록) - theme.css @layer utilities로 직접 정의 (Tailwind v4 복합 이름 매핑 실패 대응): text-heading/label/hint/on-vivid/on-bright, bg-surface-raised/overlay - badgeVariants (CVA) 재구축: 8 intent x 4 size, rem 기반, !important 제거 - Badge 컴포넌트가 cn(badgeVariants, className)로 override 허용 - DataTable width 의미 변경: 고정 -> 선호 최소 너비 (minWidth), truncate + title 툴팁 - dateFormat.ts sv-SE 로케일로 YYYY-MM-DD HH:mm:ss 일관된 KST 출력 - ColorPicker 신규 (팔레트 + native color + hex 입력) - shared/constants/ 19개 카탈로그: violation/alert/event/enforcement/patrol/ engine/userRole/device/parentResolution/modelDeployment/gearGroup/darkVessel/ httpStatus/userAccount/loginResult/permission/vesselAnalysis/connection/trainingZone + kpiUiMap. 백엔드 enum/code_master 기반 SSOT - i18n ko/en common.json에 카테고리 섹션 추가 - adminApi.fetchRoles()가 updateRoleColorCache 자동 호출 - 공통 컴포넌트 (ExcelExport/NotificationBanner/Pagination/SaveButton) 시맨틱 토큰 적용
54 lines
1.8 KiB
TypeScript
54 lines
1.8 KiB
TypeScript
/**
|
|
* 날짜/시간 포맷 유틸 — KST(Asia/Seoul) 고정 출력.
|
|
*
|
|
* 서버에서 UTC ISO 문자열이 오든, Date 객체가 오든
|
|
* 항상 KST로 변환하여 표시합니다.
|
|
*/
|
|
|
|
const KST: Intl.DateTimeFormatOptions = { timeZone: 'Asia/Seoul' };
|
|
|
|
/** 2026-04-07 14:30:00 형식 (KST). sv-SE 로케일은 ISO 유사 출력을 보장. */
|
|
export const formatDateTime = (value: string | Date | null | undefined): string => {
|
|
if (!value) return '-';
|
|
const d = typeof value === 'string' ? new Date(value) : value;
|
|
if (isNaN(d.getTime())) return '-';
|
|
return d.toLocaleString('sv-SE', {
|
|
...KST,
|
|
year: 'numeric', month: '2-digit', day: '2-digit',
|
|
hour: '2-digit', minute: '2-digit', second: '2-digit',
|
|
hour12: false,
|
|
});
|
|
};
|
|
|
|
/** 2026-04-07 형식 (KST) */
|
|
export const formatDate = (value: string | Date | null | undefined): string => {
|
|
if (!value) return '-';
|
|
const d = typeof value === 'string' ? new Date(value) : value;
|
|
if (isNaN(d.getTime())) return '-';
|
|
return d.toLocaleDateString('sv-SE', {
|
|
...KST,
|
|
year: 'numeric', month: '2-digit', day: '2-digit',
|
|
});
|
|
};
|
|
|
|
/** 14:30:00 형식 (KST) */
|
|
export const formatTime = (value: string | Date | null | undefined): string => {
|
|
if (!value) return '-';
|
|
const d = typeof value === 'string' ? new Date(value) : value;
|
|
if (isNaN(d.getTime())) return '-';
|
|
return d.toLocaleTimeString('sv-SE', {
|
|
...KST,
|
|
hour: '2-digit', minute: '2-digit', second: '2-digit',
|
|
hour12: false,
|
|
});
|
|
};
|
|
|
|
/** yyyy-MM-dd 형식 문자열 (KST 기준, API 파라미터용) */
|
|
export const toDateParam = (d: Date = new Date()): string => {
|
|
const kst = new Date(d.toLocaleString('en-US', KST));
|
|
const y = kst.getFullYear();
|
|
const m = String(kst.getMonth() + 1).padStart(2, '0');
|
|
const day = String(kst.getDate()).padStart(2, '0');
|
|
return `${y}-${m}-${day}`;
|
|
};
|