Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Zap Laravel Package

laraveljutsu/zap

Zap is a Laravel scheduling package to manage availabilities, appointments, blocked times, and custom schedules for any resource (doctors, rooms, employees). Query availability, prevent overlaps, and build booking, shift, or shared space workflows.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation

    composer require laraveljutsu/zap
    php artisan vendor:publish --provider="Zap\ZapServiceProvider"
    php artisan migrate
    
  2. Make a Model Schedulable Add the HasSchedules trait to your model (e.g., Doctor, Room):

    use Zap\Models\Concerns\HasSchedules;
    
    class Doctor extends Model
    {
        use HasSchedules;
    }
    
  3. First Use Case: Define Working Hours

    use Zap\Facades\Zap;
    
    Zap::for($doctor)
        ->named('Office Hours')
        ->availability()
        ->forYear(2025)
        ->addPeriod('09:00', '12:00')
        ->weekly(['monday', 'tuesday', 'wednesday', 'thursday', 'friday'])
        ->save();
    
  4. Check Availability

    $slots = $doctor->getBookableSlots('2025-01-15', 60, 15); // 60-min slots, 15-min buffer
    

Where to Look First

  • Documentation: laravel-zap.com
  • Quick Start: Focus on availability(), blocked(), and appointment() methods in the Quick Start section.
  • Recurrence Patterns: Refer to the Schedule Patterns table for common use cases.

Implementation Patterns

Core Workflows

1. Defining Schedules

  • Availability: Define when a resource can be booked.
    Zap::for($resource)
        ->named('Working Hours')
        ->availability()
        ->weekly(['monday', 'friday'], '09:00', '17:00')
        ->forYear(2025)
        ->save();
    
  • Blocked Times: Explicitly mark unavailable periods.
    Zap::for($resource)
        ->named('Lunch Break')
        ->blocked()
        ->addPeriod('12:00', '13:00')
        ->weekly(['monday', 'tuesday', 'wednesday', 'thursday', 'friday'])
        ->save();
    
  • Appointments: Book a slot.
    Zap::for($resource)
        ->named('Patient Consultation')
        ->appointment()
        ->from('2025-01-15')
        ->addPeriod('10:00', '11:00')
        ->withMetadata(['patient_id' => 1])
        ->save();
    

2. Querying Availability

  • Check if a time slot is bookable:
    $isBookable = $doctor->isBookableAt('2025-01-15', 60); // 60-min slot
    $isBookableAtTime = $doctor->isBookableAtTime('2025-01-15', '09:00', '09:30');
    
  • Fetch bookable slots for a day:
    $slots = $doctor->getBookableSlots('2025-01-15', 30, 10); // 30-min slots, 10-min buffer
    
  • Find the next available slot:
    $nextSlot = $doctor->getNextBookableSlot('2025-01-15', 30, 10);
    

3. Recurring Schedules

Use recurrence patterns for repeating schedules:

// Weekly on specific days
Zap::for($resource)
    ->named('Weekly Meeting')
    ->availability()
    ->weekly(['monday', 'wednesday', 'friday'])
    ->forYear(2025)
    ->addPeriod('10:00', '11:00')
    ->save();

// Monthly on the 1st and 15th
Zap::for($resource)
    ->named('Monthly Tasks')
    ->availability()
    ->monthly(['days_of_month' => [1, 15]])
    ->forYear(2025)
    ->addPeriod('09:00', '12:00')
    ->save();

// Ordinal weekday (e.g., 2nd Friday of the month)
Zap::for($resource)
    ->named('Bi-weekly Report')
    ->secondFridayOfMonth()
    ->forYear(2025)
    ->addPeriod('14:00', '15:00')
    ->save();

4. Conflict Detection

Validate schedules before saving to avoid overlaps:

$schedule = Zap::for($doctor)
    ->named('New Appointment')
    ->appointment()
    ->from('2025-01-15')
    ->addPeriod('10:00', '11:00');

if (Zap::hasConflicts($schedule)) {
    // Handle conflict (e.g., notify user or adjust time)
} else {
    $schedule->save();
}

5. Metadata and Custom Rules

Attach metadata to schedules and enforce custom rules:

Zap::for($resource)
    ->named('Custom Event')
    ->custom()
    ->from('2025-01-15')
    ->addPeriod('15:00', '16:00')
    ->noOverlap() // Prevent overlaps with other schedules
    ->maxDuration(120) // Max 2-hour duration
    ->withMetadata(['event_type' => 'workshop', 'attendees' => 5])
    ->save();

Integration Tips

  1. Laravel Events: Trigger events for schedule creation/modification/deletion:

    // In your Zap schedule builder
    ->save(); // Automatically dispatches `Zap\Events\ScheduleCreated`
    
    // Listen to events
    event(new Zap\Events\ScheduleCreated($schedule));
    
  2. API Endpoints: Expose availability checks and booking logic via API:

    Route::get('/bookable-slots/{resource}', function ($resource) {
        return response()->json($resource->getBookableSlots(now()->format('Y-m-d'), 30, 10));
    });
    
  3. Frontend Integration: Use the getBookableSlots method to power frontend calendars (e.g., FullCalendar):

    // Fetch slots for a date
    fetch(`/api/bookable-slots/${resourceId}?date=${date}`)
        .then(response => response.json())
        .then(slots => {
            // Render slots in calendar
        });
    
  4. Validation: Use Zap’s validation rules in Laravel’s form requests:

    use Zap\Rules\NoOverlap;
    
    public function rules()
    {
        return [
            'start_time' => ['required', new NoOverlap($resource, '2025-01-15', '09:00', '10:00')],
        ];
    }
    
  5. Testing: Use Zap’s testing helpers to assert schedule behavior:

    public function test_availability()
    {
        $doctor = Doctor::factory()->create();
        $doctor->setAvailability('09:00', '17:00', ['monday', 'tuesday']);
    
        $this->assertTrue($doctor->isBookableAt('2025-01-06', 60)); // Monday
        $this->assertFalse($doctor->isBookableAt('2025-01-07', 60)); // Tuesday (if not in availability)
    }
    

Gotchas and Tips

Pitfalls

  1. Timezone Mismatches:

    • Zap normalizes timezones internally, but ensure your application and database use the same timezone. Configure in config/app.php:
      'timezone' => 'UTC',
      
    • Fix: Explicitly set timezone in schedules if needed:
      Zap::for($resource)
          ->named('Timezone-Specific Schedule')
          ->availability()
          ->timezone('America/New_York')
          ->addPeriod('09:00', '17:00')
          ->weekly(['monday', 'friday'])
          ->save();
      
  2. UUID/ULID Primary Keys:

    • If your models use UUIDs/ULIDs, extend Zap’s models and update migrations/config before running migrations:
      // app/Models/Schedule.php
      use Zap\Models\Schedule as BaseSchedule;
      use Illuminate\Database\Eloquent\Concerns\HasUuids;
      
      class Schedule extends BaseSchedule
      {
          use HasUuids;
      }
      
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
calmfox/watch-sylius
damienfern/grpc-symfony-bundle
atoolo/index-bundle
atoolo/genai-bundle
coprotoai/laravel-ticket
davidjln/llm-carbon-bundle
cryonighter/valid-request-bundle
coolms/taxonomy-bundle
coolms/field-bundle
articulate-orm/symfony
aaix/laravel-tall-architect
ephoto/akeneo-connector
emmanuelballery/eb-plantumlbundle
emielburgman/symfony-visitor-beacon
emielburgman/symfony-visit-storage
emielburgman/symfony-security-headers
emielburgman/symfony-log-viewer
emarref/xdebug-bundle
emarref/pubnub-bundle
elriseio/finance-money-bundle