feat(WEB): CEO 대시보드 캘린더 강화 및 validation 모듈 분리

- CalendarSection 일정 CRUD 기능 확장 (상세 모달 연동)
- ScheduleDetailModal 개선
- CEO 대시보드 섹션별 API 키 통일
- validation.ts → validation/ 모듈 분리 (item-schemas, utils)
- formatters.ts 확장
- date.ts 유틸 추가
- SignupPage/EmployeeForm/AddCompanyDialog 등 소규모 개선
- PaymentHistory/PopupManagement utils 정리

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
유병철
2026-02-24 13:01:41 +09:00
parent 6a469181cd
commit b8dfa3d887
24 changed files with 726 additions and 502 deletions

View File

@@ -20,6 +20,7 @@ import {
AlertDialogHeader,
AlertDialogTitle,
} from '@/components/ui/alert-dialog';
import { extractDigits } from '@/lib/formatters';
interface AddCompanyDialogProps {
open: boolean;
@@ -36,7 +37,7 @@ export function AddCompanyDialog({ open, onOpenChange }: AddCompanyDialogProps)
// 숫자만 입력 가능 (10자리 제한)
const handleBusinessNumberChange = (value: string) => {
const numbersOnly = value.replace(/[^0-9]/g, '');
const numbersOnly = extractDigits(value);
if (numbersOnly.length <= 10) {
setBusinessNumber(numbersOnly);
}

View File

@@ -1,6 +1,6 @@
import type { PaymentApiData, PaymentHistory, PaymentStatus } from './types';
import { PAYMENT_METHOD_LABELS } from './types';
import { formatDate } from '@/lib/utils/date';
import { formatDate, toDateString } from '@/lib/utils/date';
// ===== API → Frontend 변환 =====
export function transformApiToFrontend(apiData: PaymentApiData): PaymentHistory {
@@ -11,12 +11,12 @@ export function transformApiToFrontend(apiData: PaymentApiData): PaymentHistory
const paymentMethodLabel = PAYMENT_METHOD_LABELS[apiData.payment_method] || apiData.payment_method;
// 구독 기간
const periodStart = subscription?.started_at?.split('T')[0] || '';
const periodEnd = subscription?.ended_at?.split('T')[0] || '';
const periodStart = toDateString(subscription?.started_at);
const periodEnd = toDateString(subscription?.ended_at);
return {
id: String(apiData.id),
paymentDate: apiData.paid_at?.split('T')[0] || formatDate(apiData.created_at),
paymentDate: toDateString(apiData.paid_at) || formatDate(apiData.created_at),
subscriptionName: plan?.name || '구독',
paymentMethod: paymentMethodLabel,
subscriptionPeriod: {

View File

@@ -3,6 +3,7 @@
*/
import type { Popup, PopupFormData, PopupTarget, PopupStatus } from './types';
import { toDateString } from '@/lib/utils/date';
// ============================================
// API 응답 타입 정의
@@ -55,9 +56,9 @@ export function transformApiToFrontend(apiData: PopupApiData): Popup {
status: apiData.status as PopupStatus,
author: apiData.creator?.name || '관리자',
authorId: apiData.created_by ? String(apiData.created_by) : '',
createdAt: apiData.created_at?.split('T')[0] || '',
startDate: apiData.started_at?.split('T')[0] || '',
endDate: apiData.ended_at?.split('T')[0] || '',
createdAt: toDateString(apiData.created_at),
startDate: toDateString(apiData.started_at),
endDate: toDateString(apiData.ended_at),
};
}