Files
ai-agent/web/app/dashboard/agent-team-schedules/_components/calendar-time-layout.ts
T

88 lines
2.6 KiB
TypeScript

const dayMs = 24 * 60 * 60 * 1000
export type TimeLayoutSchedule = {
id: number
startAt: string
endAt: string
}
export type TimeLayoutItem = {
leftPercent: number
widthPercent: number
startLabel: string
endLabel: string
}
export type DayTimeLayout = {
rangeLabel: string
items: Map<number, TimeLayoutItem>
}
function parseLocalDateTime(value: string) {
const match = value.match(/^(\d{4})-(\d{2})-(\d{2})[ T](\d{2}):(\d{2})(?::(\d{2}))?/)
if (!match) {
return new Date(value)
}
return new Date(
Number(match[1]),
Number(match[2]) - 1,
Number(match[3]),
Number(match[4]),
Number(match[5]),
Number(match[6] ?? 0)
)
}
function startOfDay(date: Date) {
const ret = new Date(date)
ret.setHours(0, 0, 0, 0)
return ret
}
function formatTime(date: Date) {
const hour = String(date.getHours()).padStart(2, "0")
const minute = String(date.getMinutes()).padStart(2, "0")
return `${hour}:${minute}`
}
function roundPercent(value: number) {
return Math.round(value * 100) / 100
}
export function buildDayTimeLayout(schedules: TimeLayoutSchedule[], day: Date): DayTimeLayout {
const dayStart = startOfDay(day)
const dayEnd = new Date(dayStart.getTime() + dayMs)
const visibleItems = schedules
.map((item) => {
const scheduleStart = parseLocalDateTime(item.startAt)
const scheduleEnd = parseLocalDateTime(item.endAt)
const visibleStart = new Date(Math.max(scheduleStart.getTime(), dayStart.getTime()))
const visibleEnd = new Date(Math.min(scheduleEnd.getTime(), dayEnd.getTime()))
return { item, visibleStart, visibleEnd }
})
.filter(({ visibleStart, visibleEnd }) => visibleEnd > visibleStart)
if (visibleItems.length === 0) {
return { rangeLabel: "", items: new Map() }
}
const rangeStart = new Date(Math.min(...visibleItems.map(({ visibleStart }) => visibleStart.getTime())))
const rangeEnd = new Date(Math.max(...visibleItems.map(({ visibleEnd }) => visibleEnd.getTime())))
const rangeMs = Math.max(rangeEnd.getTime() - rangeStart.getTime(), 1)
const items = new Map<number, TimeLayoutItem>()
visibleItems.forEach(({ item, visibleStart, visibleEnd }) => {
items.set(item.id, {
leftPercent: roundPercent(((visibleStart.getTime() - rangeStart.getTime()) / rangeMs) * 100),
widthPercent: roundPercent(((visibleEnd.getTime() - visibleStart.getTime()) / rangeMs) * 100),
startLabel: formatTime(visibleStart),
endLabel: formatTime(visibleEnd),
})
})
return {
rangeLabel: `${formatTime(rangeStart)} - ${formatTime(rangeEnd)}`,
items,
}
}