스켈레톤 시스템: - 타이틀은 항상 표시, 나머지 영역만 스켈레톤 처리 - 헤더 액션, 검색, 테이블 영역 개별 스켈레톤 적용 달력 UI: - 경계선 색상 border-gray-200으로 통일 - 지난 일자 배경색 bg-gray-300으로 더 어둡게 - 선택/오늘 날짜 색상 보라색으로 변경 (이벤트 바와 구분) - 날짜-이벤트 바 간격 8px 추가 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
96 lines
2.8 KiB
TypeScript
96 lines
2.8 KiB
TypeScript
'use client';
|
|
|
|
import { cn } from '@/components/ui/utils';
|
|
import type { ScheduleEvent } from './types';
|
|
import { EVENT_COLORS } from './types';
|
|
import {
|
|
Tooltip,
|
|
TooltipContent,
|
|
TooltipProvider,
|
|
TooltipTrigger,
|
|
} from '@/components/ui/tooltip';
|
|
|
|
interface ScheduleBarProps {
|
|
event: ScheduleEvent;
|
|
/** 현재 주에서 시작하는지 */
|
|
isStart: boolean;
|
|
/** 현재 주에서 끝나는지 */
|
|
isEnd: boolean;
|
|
/** 차지하는 컬럼 수 (1-7) */
|
|
colSpan: number;
|
|
/** 시작 위치 (0-6) */
|
|
startCol: number;
|
|
/** 행 인덱스 (겹치는 이벤트 처리) */
|
|
rowIndex: number;
|
|
onClick: (event: ScheduleEvent) => void;
|
|
}
|
|
|
|
/**
|
|
* 일정 바 컴포넌트
|
|
* - 일정 바 렌더링 (시작~종료 날짜)
|
|
* - 여러 날에 걸치는 바 표시
|
|
* - 색상 구분 (상태별)
|
|
* - 호버/클릭 이벤트
|
|
* - 툴팁으로 담당자/기간 정보 표시
|
|
*/
|
|
export function ScheduleBar({
|
|
event,
|
|
isStart,
|
|
isEnd,
|
|
colSpan,
|
|
startCol,
|
|
rowIndex,
|
|
onClick,
|
|
}: ScheduleBarProps) {
|
|
const color = event.color || 'blue';
|
|
const colorClass = EVENT_COLORS[color] || EVENT_COLORS.blue;
|
|
|
|
// 컬럼 너비 계산 (각 셀은 1/7)
|
|
const widthPercent = (colSpan / 7) * 100;
|
|
const leftPercent = (startCol / 7) * 100;
|
|
|
|
// 툴팁 내용 생성
|
|
const tooltipContent = `${event.title}\n기간: ${event.startDate} ~ ${event.endDate}`;
|
|
|
|
return (
|
|
<TooltipProvider delayDuration={200}>
|
|
<Tooltip>
|
|
<TooltipTrigger asChild>
|
|
<button
|
|
type="button"
|
|
onClick={(e) => {
|
|
e.stopPropagation();
|
|
onClick(event);
|
|
}}
|
|
className={cn(
|
|
'absolute h-5 px-2 text-xs font-medium truncate',
|
|
'transition-all hover:opacity-80 hover:shadow-sm',
|
|
'flex items-center cursor-pointer',
|
|
colorClass,
|
|
// 라운드 처리
|
|
isStart && isEnd && 'rounded-md',
|
|
isStart && !isEnd && 'rounded-l-md',
|
|
!isStart && isEnd && 'rounded-r-md',
|
|
!isStart && !isEnd && 'rounded-none'
|
|
)}
|
|
style={{
|
|
width: `calc(${widthPercent}% - 4px)`,
|
|
left: `calc(${leftPercent}% + 2px)`,
|
|
top: `${rowIndex * 24 + 40}px`, // 날짜 영역(40px) 아래부터 시작 (간격 8px 추가)
|
|
}}
|
|
>
|
|
{isStart && <span className="truncate">{event.title}</span>}
|
|
</button>
|
|
</TooltipTrigger>
|
|
<TooltipContent side="top" className="max-w-xs">
|
|
<div className="text-sm">
|
|
<p className="font-medium">{event.title}</p>
|
|
<p className="text-muted-foreground text-xs mt-1">
|
|
기간: {event.startDate} ~ {event.endDate}
|
|
</p>
|
|
</div>
|
|
</TooltipContent>
|
|
</Tooltip>
|
|
</TooltipProvider>
|
|
);
|
|
} |