import {
Calendar,
DayGrid,
List,
TimeGrid,
useCalendar,
useCalendarController,
type EventInput,
type EventSourceInput,
type FetchInfo,
} from 'z-cal/react'
import type { JSX } from 'react'
import { useScheme } from '../DemoFrame'
import { today, todayDate } from '../shared/dates'
const PLUGINS = [DayGrid, TimeGrid, List]
// Source 1: a static array. Wrapped as a function source so it merges with the others
// (`events` alone is only consulted when there are no `eventSources`).
const STATIC: EventInput[] = [
{ id: 'sync', title: 'Team sync', start: today(0, 10), end: today(0, 11) },
{ id: 'conf', title: 'Conference', start: todayDate(1), end: todayDate(4) },
]
// Source 2: an async function with ~300 ms latency. It receives the visible range and
// generates events relative to it, so paging always yields data.
const asyncSource: EventSourceInput = {
events: (info: FetchInfo) =>
new Promise<EventInput[]>((resolve) => {
const first = info.start.toPlainDate()
setTimeout(
() =>
resolve([
{
id: 'yoga',
title: 'Yoga (async)',
start: `${first.add({ days: 1 }).toString()}T07:00`,
end: `${first.add({ days: 1 }).toString()}T08:00`,
color: 'oklch(60% 0.15 150)',
},
{
id: 'review',
title: 'Design review (async)',
start: `${first.add({ days: 3 }).toString()}T16:00`,
end: `${first.add({ days: 3 }).toString()}T17:00`,
color: 'oklch(60% 0.15 150)',
},
]),
300,
)
}),
}
// Source 3: a JSON feed, fetched with `?start=&end=&timeZone=` for the visible range.
const SOURCES: EventSourceInput[] = [
{ events: (_info, success) => success(STATIC) },
asyncSource,
{ url: '/events.json' },
]
export function EventSourcesDemo(): JSX.Element {
const { ref, calendar } = useCalendar()
// The controller mirrors instance state (view, title, loading) into React.
const controller = useCalendarController(calendar)
return (
<>
<p className="controls">
<span>Sources: static array, async function, JSON feed</span>
<output className="loading-status">{controller.loading ? 'loading…' : ''}</output>
</p>
<div className="card">
<Calendar
ref={ref}
plugins={PLUGINS}
view="dayGridMonth"
colorScheme={useScheme()}
headerToolbar={{
start: 'title',
center: '',
end: 'today prev,next dayGridMonth,timeGridWeek,listWeek',
}}
buttonText={{ listWeek: 'list' }}
eventSources={SOURCES}
height="600px"
/>
</div>
</>
)
}