feat(WEB): 공사관리 리스트 공통화 및 캘린더/포맷터 기능 개선
공사관리 리스트 공통화: - 입찰/계약/견적/인수인계/이슈/품목/노무/현장/파트너/단가/기성/현장브리핑/구조검토/유틸리티/작업자현황 리스트 공통 포맷터 적용 - 중복 포맷팅 로직 제거 (-530줄) 캘린더 기능 개선: - CEODashboard CalendarSection 기능 확장 - ScheduleCalendar DayCell/MonthView/WeekView 개선 - ui/calendar 컴포넌트 기능 추가 유틸리티 개선: - date.ts 날짜 유틸 함수 추가 - formatAmount.ts 금액 포맷 함수 추가 신규 추가: - useListHandlers 훅 추가 - src/constants/ 디렉토리 추가 - 포맷터 공통화 계획 문서 추가 - SAM ERP/MES 정체성 분석 문서 추가 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -10,7 +10,10 @@ interface DayCellProps {
|
||||
isCurrentMonth: boolean;
|
||||
isToday: boolean;
|
||||
isSelected: boolean;
|
||||
isWeekend: boolean;
|
||||
isSaturday: boolean;
|
||||
isSunday: boolean;
|
||||
isHoliday?: boolean;
|
||||
holidayName?: string | null;
|
||||
isPast: boolean;
|
||||
badge?: DayBadge;
|
||||
onClick: (date: Date) => void;
|
||||
@@ -28,18 +31,24 @@ export function DayCell({
|
||||
isCurrentMonth,
|
||||
isToday,
|
||||
isSelected,
|
||||
isWeekend,
|
||||
isSaturday,
|
||||
isSunday,
|
||||
isHoliday = false,
|
||||
holidayName,
|
||||
isPast,
|
||||
badge,
|
||||
onClick,
|
||||
}: DayCellProps) {
|
||||
const dayNumber = format(date, 'd');
|
||||
const badgeColor = badge?.color || 'red';
|
||||
const isRedDay = isSunday || isHoliday; // 일요일 또는 공휴일 → 빨간색
|
||||
const isBlueDay = isSaturday && !isHoliday; // 토요일(공휴일 아닌 경우) → 파란색
|
||||
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => onClick(date)}
|
||||
title={holidayName || undefined}
|
||||
className={cn(
|
||||
'relative w-full h-8 flex items-center justify-center',
|
||||
'text-sm font-medium transition-colors rounded-md',
|
||||
@@ -48,10 +57,14 @@ export function DayCell({
|
||||
isCurrentMonth ? 'text-foreground' : 'text-muted-foreground/40',
|
||||
// 지난 일자 - 더 명확한 회색 (현재 월에서만)
|
||||
isPast && isCurrentMonth && !isToday && !isSelected && 'text-gray-400',
|
||||
// 주말 색상 (지난 일자가 아닌 경우만)
|
||||
isWeekend && isCurrentMonth && !isPast && 'text-red-500',
|
||||
// 지난 주말 - 연한 색상
|
||||
isWeekend && isCurrentMonth && isPast && !isToday && !isSelected && 'text-red-300',
|
||||
// 일요일/공휴일 색상 (지난 일자가 아닌 경우만) → 빨간색
|
||||
isRedDay && isCurrentMonth && !isPast && 'text-red-500',
|
||||
// 토요일 색상 (지난 일자가 아닌 경우만) → 파란색
|
||||
isBlueDay && isCurrentMonth && !isPast && 'text-blue-500',
|
||||
// 지난 일요일/공휴일 - 연한 색상
|
||||
isRedDay && isCurrentMonth && isPast && !isToday && !isSelected && 'text-red-300',
|
||||
// 지난 토요일 - 연한 파란색
|
||||
isBlueDay && isCurrentMonth && isPast && !isToday && !isSelected && 'text-blue-300',
|
||||
// 오늘 - 굵은 글씨 (외곽선은 부모 셀에 적용) - 보라색
|
||||
isToday && !isSelected && 'font-bold text-purple-600',
|
||||
// 선택됨 - 배경색 하이라이트 - 보라색
|
||||
|
||||
@@ -19,7 +19,8 @@ import {
|
||||
getEventsForDate,
|
||||
getBadgeForDate,
|
||||
} from './utils';
|
||||
import { getDay } from 'date-fns';
|
||||
import { getDay, format } from 'date-fns';
|
||||
import { isHoliday, getHolidayName } from '@/constants/calendarEvents';
|
||||
|
||||
/**
|
||||
* 월간 뷰 컴포넌트
|
||||
@@ -65,9 +66,14 @@ export function MonthView({
|
||||
{/* 요일 헤더 */}
|
||||
<div className="grid grid-cols-7 mb-1">
|
||||
{weekdayHeaders.map((day, index) => {
|
||||
const isWeekend =
|
||||
(weekStartsOn === 0 && (index === 0 || index === 6)) ||
|
||||
(weekStartsOn === 1 && (index === 5 || index === 6));
|
||||
// 일요일: weekStartsOn=0이면 index 0, weekStartsOn=1이면 index 6
|
||||
const isSunday =
|
||||
(weekStartsOn === 0 && index === 0) ||
|
||||
(weekStartsOn === 1 && index === 6);
|
||||
// 토요일: weekStartsOn=0이면 index 6, weekStartsOn=1이면 index 5
|
||||
const isSaturday =
|
||||
(weekStartsOn === 0 && index === 6) ||
|
||||
(weekStartsOn === 1 && index === 5);
|
||||
|
||||
return (
|
||||
<div
|
||||
@@ -75,7 +81,8 @@ export function MonthView({
|
||||
className={cn(
|
||||
'text-center text-xs font-semibold py-2',
|
||||
'text-muted-foreground',
|
||||
isWeekend && 'text-red-400'
|
||||
isSunday && 'text-red-400',
|
||||
isSaturday && 'text-blue-400'
|
||||
)}
|
||||
>
|
||||
{day}
|
||||
@@ -168,7 +175,11 @@ function WeekRow({
|
||||
{/* 날짜 셀들 */}
|
||||
{weekDays.map((date, colIndex) => {
|
||||
const dayOfWeek = getDay(date);
|
||||
const isWeekend = dayOfWeek === 0 || dayOfWeek === 6;
|
||||
const isSaturday = dayOfWeek === 6;
|
||||
const isSunday = dayOfWeek === 0;
|
||||
const dateStr = format(date, 'yyyy-MM-dd');
|
||||
const isHolidayDate = isHoliday(dateStr);
|
||||
const holidayName = getHolidayName(dateStr);
|
||||
const badge = getBadgeForDate(badges, date);
|
||||
const hiddenCount = hiddenEventCounts.get(colIndex) || 0;
|
||||
const dayEvents = getEventsForDate(events, date);
|
||||
@@ -201,7 +212,10 @@ function WeekRow({
|
||||
isCurrentMonth={isCurrMonth}
|
||||
isToday={isToday}
|
||||
isSelected={isSelected}
|
||||
isWeekend={isWeekend}
|
||||
isSaturday={isSaturday}
|
||||
isSunday={isSunday}
|
||||
isHoliday={isHolidayDate}
|
||||
holidayName={holidayName}
|
||||
isPast={isPast}
|
||||
badge={badge}
|
||||
onClick={onDateClick}
|
||||
|
||||
@@ -17,6 +17,7 @@ import {
|
||||
} from './utils';
|
||||
import { format, getDay } from 'date-fns';
|
||||
import { ko } from 'date-fns/locale';
|
||||
import { isHoliday, getHolidayName } from '@/constants/calendarEvents';
|
||||
|
||||
/**
|
||||
* 주간 뷰 컴포넌트
|
||||
@@ -81,7 +82,13 @@ export function WeekView({
|
||||
<div className="grid grid-cols-7 mb-1">
|
||||
{weekDays.map((date) => {
|
||||
const dayOfWeek = getDay(date);
|
||||
const isWeekend = dayOfWeek === 0 || dayOfWeek === 6;
|
||||
const isSaturday = dayOfWeek === 6;
|
||||
const isSunday = dayOfWeek === 0;
|
||||
const dateStr = format(date, 'yyyy-MM-dd');
|
||||
const isHolidayDate = isHoliday(dateStr);
|
||||
const holidayName = getHolidayName(dateStr);
|
||||
const isRedDay = isSunday || isHolidayDate; // 일요일 또는 공휴일 → 빨간색
|
||||
const isBlueDay = isSaturday && !isHolidayDate; // 토요일(공휴일 아닌 경우) → 파란색
|
||||
const isToday = checkIsToday(date);
|
||||
|
||||
return (
|
||||
@@ -91,11 +98,13 @@ export function WeekView({
|
||||
'text-center py-2',
|
||||
'flex flex-col items-center'
|
||||
)}
|
||||
title={holidayName || undefined}
|
||||
>
|
||||
<span
|
||||
className={cn(
|
||||
'text-xs font-semibold text-muted-foreground',
|
||||
isWeekend && 'text-red-400'
|
||||
isRedDay && 'text-red-400',
|
||||
isBlueDay && 'text-blue-400'
|
||||
)}
|
||||
>
|
||||
{format(date, 'E', { locale: ko })}
|
||||
@@ -103,7 +112,8 @@ export function WeekView({
|
||||
<span
|
||||
className={cn(
|
||||
'text-lg font-bold mt-0.5',
|
||||
isWeekend && 'text-red-500',
|
||||
isRedDay && 'text-red-500',
|
||||
isBlueDay && 'text-blue-500',
|
||||
isToday && 'bg-primary text-primary-foreground rounded-full w-8 h-8 flex items-center justify-center'
|
||||
)}
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user