API Reference

Availability & Conflicts

Managing availability and handling schedule conflicts.

Checking Availability

Basic Availability Check

// Check if available at specific time
$available = $user->isAvailableAt('2025-03-15', '14:00', '16:00');

if ($available) {
    // User is available, proceed with booking
}

Getting Available Slots

// Get available time slots for a day
$slots = $user->getAvailableSlots(
    date: '2025-03-15',
    dayStart: '09:00',
    dayEnd: '17:00',
    slotDuration: 60 // 1-hour slots
);

foreach ($slots as $slot) {
    echo "Available: {$slot['start_time']} - {$slot['end_time']}";
}

Getting Available Slots with Buffer Time

// Get available slots with buffer time between appointments
$slots = $user->getAvailableSlots(
    date: '2025-03-15',
    dayStart: '09:00',
    dayEnd: '17:00',
    slotDuration: 60,
    bufferMinutes: 15 // 15 minutes between appointments
);

foreach ($slots as $slot) {
    echo "Available: {$slot['start_time']} - {$slot['end_time']} (Buffer: {$slot['buffer_minutes']} min)";
}

Getting Bookable Slots (Availability-Based)

// Get bookable slots that respect availability schedules
$slots = $user->getBookableSlots(
    date: '2025-03-15',
    slotDuration: 60,
    bufferMinutes: 10
);

foreach ($slots as $slot) {
    if ($slot['is_available']) {
        echo "Bookable: {$slot['start_time']} - {$slot['end_time']}";
    }
}

Finding Next Available Slot

// Find next available slot after a specific date
$nextSlot = $user->getNextAvailableSlot(
    afterDate: '2025-03-15',
    duration: 120, // 2 hours needed
    dayStart: '09:00',
    dayEnd: '17:00'
);

if ($nextSlot) {
    echo "Next available: {$nextSlot['date']} from {$nextSlot['start_time']} to {$nextSlot['end_time']}";
}

Finding Next Available Slot with Buffer Time

// Find next available slot with buffer time
$nextSlot = $user->getNextAvailableSlot(
    afterDate: '2025-03-15',
    duration: 120, // 2 hours needed
    dayStart: '09:00',
    dayEnd: '17:00',
    bufferMinutes: 10 // 10 minutes buffer
);

if ($nextSlot) {
    echo "Next available: {$nextSlot['date']} from {$nextSlot['start_time']} to {$nextSlot['end_time']} (Buffer: {$nextSlot['buffer_minutes']} min)";
}

Finding Next Bookable Slot

// Find next bookable slot that respects availability schedules
$nextSlot = $user->getNextBookableSlot(
    afterDate: '2025-03-15',
    duration: 90, // 1.5 hours needed
    bufferMinutes: 15
);

if ($nextSlot) {
    echo "Next bookable: {$nextSlot['date']} from {$nextSlot['start_time']} to {$nextSlot['end_time']}";
}

Conflict Management

Automatic Conflict Detection

use Zap\Exceptions\ScheduleConflictException;

try {
    $schedule = Zap::for($user)
        ->named('Important Meeting')
        ->from('2025-03-15')
        ->addPeriod('14:00', '16:00')
        ->noOverlap() // Enable conflict detection
        ->save();
} catch (ScheduleConflictException $e) {
    // Handle conflicts gracefully
    $conflicts = $e->getConflictingSchedules();

    foreach ($conflicts as $conflict) {
        echo "Conflicts with: {$conflict->name}";
    }
}

Manual Conflict Checking

// Check for conflicts before saving
$conflicts = Zap::findConflicts($schedule);

if (!empty($conflicts)) {
    // Handle conflicts
    foreach ($conflicts as $conflict) {
        echo "Conflict detected with: {$conflict->name}";
    }
} else {
    // Safe to proceed
    $schedule->save();
}

Buffer Time Configuration

Global Buffer Time

Configure default buffer time in your config/zap.php file:

'time_slots' => [
    'buffer_minutes' => 10, // 10 minutes between all appointments
    'default_duration' => 60,
    'min_duration' => 15,
    'max_duration' => 480,
    // ... other settings
],

Using Global Buffer Time

// Use global buffer time (falls back to config)
$slots = $user->getAvailableSlots('2025-03-15', '09:00', '17:00', 60);

// Override with specific buffer time
$slots = $user->getAvailableSlots('2025-03-15', '09:00', '17:00', 60, 15);

// Explicitly disable buffer (override config)
$slots = $user->getAvailableSlots('2025-03-15', '09:00', '17:00', 60, 0);

Buffer Time Examples

// Healthcare: 30-minute appointments with 10-minute cleanup
$consultationSlots = $doctor->getAvailableSlots('2025-03-15', '09:00', '17:00', 30, 10);

// Hair salon: 45-minute cuts with 15-minute cleanup
$haircutSlots = $stylist->getAvailableSlots('2025-03-15', '09:00', '18:00', 45, 15);

// Surgery: 2-hour procedures with 30-minute setup
$surgerySlots = $surgeon->getAvailableSlots('2025-03-15', '08:00', '16:00', 120, 30);

Business Rules

Working Hours Validation

The workingHoursOnly() method requires enabling the working_hours validation rule in your config file.
$schedule = Zap::for($user)
    ->named('Client Meeting')
    ->from('2025-03-15')
    ->addPeriod('14:00', '16:00')
    ->workingHoursOnly('09:00', '18:00') // Business hours only
    ->save();

Duration Limits

The maxDuration() method requires enabling the max_duration validation rule in your config file.
$schedule = Zap::for($user)
    ->named('Long Meeting')
    ->from('2025-03-15')
    ->addPeriod('14:00', '18:00')
    ->maxDuration(240) // Maximum 4 hours
    ->save();

Rule Override

// Emergency override - bypass overlap validation
$emergency = Zap::for($user)
    ->named('Emergency Meeting')
    ->from('2025-03-15')
    ->addPeriod('10:30', '12:00')
    ->withRule('no_overlap', ['enabled' => false])
    ->save();

Real-World Example: Meeting Room

// Room availability
$roomAvailability = Zap::for($room)
    ->named('Conference Room A')
    ->availability()
    ->from('2025-01-01')->to('2025-12-31')
    ->addPeriod('08:00', '18:00')
    ->weekly(['monday', 'tuesday', 'wednesday', 'thursday', 'friday'])
    ->save();

// Check if room is available
$isAvailable = $room->isAvailableAt('2025-03-15', '09:00', '11:00');

if ($isAvailable) {
    // Book the room
    $meeting = Zap::for($room)
        ->named('Board Meeting')
        ->appointment()
        ->from('2025-03-15')
        ->addPeriod('09:00', '11:00')
        ->withMetadata([
            'organizer' => 'john@company.com',
            'equipment' => ['projector', 'whiteboard']
        ])
        ->save();
}