CourseKitFrontend
useTimetable
Fetch and display schedule data for entities and date ranges
Overview
useTimetable fetches materialized schedule occurrences for a given query. It calls GET {apiUrl}/schedule with query parameters.
import { useTimetable } from '@hfu.digital/coursekit-react';Usage
function WeekSchedule({ instructorId }: { instructorId: string }) {
const { data, loading, error, refetch } = useTimetable({
dateRange: { start: '2026-03-02', end: '2026-03-08' },
instructorIds: [instructorId],
});
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return (
<ul>
{data.map(occ => (
<li key={`${occ.eventId}-${occ.occurrenceDate}`}>
{occ.originalEvent.title} at {occ.startTime}
{occ.isException && ` (${occ.exceptionType})`}
</li>
))}
</ul>
);
}Pass null to skip the query:
const { data } = useTimetable(query ?? null);TimetableQuery
interface TimetableQuery {
dateRange: { start: string; end: string };
instructorIds?: string[];
roomIds?: string[];
groupIds?: string[];
courseIds?: string[];
periodId?: string;
}All filter fields are optional. Dates are ISO 8601 strings.
TimetableOccurrence
interface TimetableOccurrence {
eventId: string;
occurrenceDate: string;
startTime: string;
durationMin: number;
roomId: string | null;
metadata: Record<string, unknown> | null;
isException: boolean;
exceptionType: 'cancelled' | 'modified' | 'added' | null;
originalEvent: {
id: string;
title: string;
[key: string]: unknown;
};
}UseTimetableResult
interface UseTimetableResult {
data: TimetableOccurrence[];
loading: boolean;
error: Error | null;
refetch: () => Promise<void>;
}| Field | Type | Description |
|---|---|---|
data | TimetableOccurrence[] | The fetched occurrences (empty while loading) |
loading | boolean | true while the request is in flight |
error | Error | null | The error if the request failed |
refetch | () => Promise<void> | Manually re-fetch the data |
API Endpoint
The hook calls:
GET {apiUrl}/schedule?startDate=...&endDate=...&instructorIds=...&roomIds=...Query parameters are only included when the corresponding filter is provided.