Files
acs/frontend/src/status.ts
unknown f0c30d8005 Initial commit: IT센터 출입자관리시스템 (ACS)
방문자 사전신청·승인, 입·출입 체크인/아웃, QR 배지, 재실현황,
블랙리스트, 대시보드 통계, 방문 리포트(엑셀)까지 7단계 전 기능 구현.

- backend: Spring Boot 3.4.5 / Java 21 (JDK 26 빌드), 세션 인증, JPA, H2/PostgreSQL, POI, ZXing, Flyway
- frontend: React 19 / Vite 6 / TypeScript
- infra: Docker Compose (db·app·web nginx), Flyway V1__init, Python 사용자 시드
- docs: 워크플로우 / 시퀀스 다이어그램(Mermaid) / 이슈·유의사항

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 08:59:41 +09:00

67 lines
2.0 KiB
TypeScript

import { VisitStatus } from './types';
export const STATUS_LABEL: Record<VisitStatus, string> = {
DRAFT: '임시저장',
PENDING: '승인대기',
APPROVED: '승인완료',
REJECTED: '반려',
CANCELLED: '취소',
EXPIRED: '만료',
};
/** CSS class suffix for the status badge color. */
export const STATUS_CLASS: Record<VisitStatus, string> = {
DRAFT: 'gray',
PENDING: 'amber',
APPROVED: 'green',
REJECTED: 'red',
CANCELLED: 'gray',
EXPIRED: 'gray',
};
export function formatDateTime(iso?: string): string {
if (!iso) return '-';
const d = new Date(iso);
if (Number.isNaN(d.getTime())) return iso;
return d.toLocaleString('ko-KR', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
});
}
const pad = (n: number) => String(n).padStart(2, '0');
/** Compact `MM.DD HH:mm` for dense tables. */
export function formatShort(iso?: string): string {
if (!iso) return '-';
const d = new Date(iso);
if (Number.isNaN(d.getTime())) return iso;
return `${pad(d.getMonth() + 1)}.${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}`;
}
/** Compact `YYYY.MM.DD HH:mm` for tight table cells. */
function compact(d: Date): string {
return `${d.getFullYear()}.${pad(d.getMonth() + 1)}.${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}`;
}
/**
* Compact visit period for table cells.
* Same day → `2026.07.01 16:29 ~ 16:33`, otherwise → `2026.07.01 16:29 ~ 2026.07.02 09:00`.
*/
export function formatVisitRange(fromIso?: string, toIso?: string): string {
if (!fromIso) return '-';
const from = new Date(fromIso);
if (Number.isNaN(from.getTime())) return fromIso;
if (!toIso) return compact(from);
const to = new Date(toIso);
if (Number.isNaN(to.getTime())) return `${compact(from)} ~ ${toIso}`;
const sameDay =
from.getFullYear() === to.getFullYear() &&
from.getMonth() === to.getMonth() &&
from.getDate() === to.getDate();
return `${compact(from)} ~ ${sameDay ? `${pad(to.getHours())}:${pad(to.getMinutes())}` : compact(to)}`;
}