Nettu scheduler
provides a Service
type that makes it really easy to build a booking application. The Service
type represents a bookable service that your app provides.
It works by adding User
s to the Service
that are going to be bookable. Each User
on the Service
can have a bunch of different settings for when they can be booked (availability schedule, the closest booking time, buffers etc.).
Then you can then easily query the Service
for the available bookingslots. When
a booking is made you can represent it as a CalendarEvent
with the booked User
as the owner of the CalendarEvent
and the User
will no longer be bookable
during that timeperiod.
An important point is to not store the booking resource itself in Nettu scheduler
, but in your own application as your application is the one that contains all the information about the participants and metadata of the booking. It is recommended that Nettu scheduler
is just going to be used for calculating bookingslots, and not to try to fit your booking data model into the CalendarEvent
resource type (unless it is a really simple one).
import { NettuClient, BusyCalendarProvider } from "@nettu/scheduler-sdk";
const client = NettuClient({ apiKey: "YOUR_API_KEY" });
// Create a Service
const serviceRes = await client.service.create();
const { service } = serviceRes.data!;
// Create a User
const userRes = await client.user.create();
const { user } = userRes.data!;
// Create a Schedule for the User
const scheduleRes = await client.schedule.create(user.id, { timezone: "Europe/Oslo" });
const { schedule } = scheduleRes.data!;
// Calendar that will be used to store bookings
const calendarRes = await client.calendar.create(user.id, {
timezone: "Europe/Oslo",
weekStart: 0
});
const { calendar } = calendarRes.data!;
// Register the User on the Service with the specified Schedule as availability and
// also a buffer time after every service event
await client.service.addUser(service.id, {
userId: user.id,
availability: {
variant: "Schedule",
id: schedule.id
},
// Make User unbookable for 10 minutes after a booking
buffer: 10
});
// Add calendars that should be used to calculate busy time
await client.service.addBusyCalendar({
serviceId: service.id,
userId: user.id,
calendar: {
id: calendar.id,
provider: BusyCalendarProvider.Nettu
}
});
// Now query for the available bookingslots
const bookingSlotsRes = await client.service.getBookingslots(service.id, {
startDate: "2030-10-10",
endDate: "2030-10-10",
ianaTz: "Europe/Oslo",
interval: 1000 * 60 * 10,
duration: 1000 * 60 * 30
});
const bookingSlotsBefore = bookingSlotsRes.data!.dates[0].slots;
// Insert a CalendarEvent that represents the booking selected
// by the end user, the User will no longer be bookable in this timeperiod
await client.events.create(user.id, {
startTs: bookingSlotsBefore[0].start,
calendarId: calendar.id,
duration: 1000 * 60 * 30, // 30 minutes in millis
serviceId: service.id, // Flagging this event as a service event so that possible service buffers will be created correctly
busy: true, // The user will be busy during this time and not bookable
// Optional if you want to receive a webhook notification 15 minutes before
// the booking
reminders: [{
delta: -15,
identifier: "remind"
}]
});
const bookingSlotsRes2 = await client.service.getBookingslots(service.id, {
startDate: "2030-10-10",
endDate: "2030-10-10",
ianaTz: "Europe/Oslo",
interval: 1000 * 60 * 10,
duration: 1000 * 60 * 15
});
const bookingSlotsAfter = bookingSlotsRes2.data!.dates[0].slots;
// See that user is no longer available during the booked event + buffer time
console.log({
before: bookingSlotsBefore.length,
after: bookingSlotsAfter.length
})