### Real-World Example: Doctor Appointment System Setup Source: https://github.com/ludoguenet/laravel-zap/blob/main/resources/boost/skills/zap-availability/SKILL.md Demonstrates a comprehensive workflow for setting up a doctor's schedule, blocking time, checking availability, and booking appointments using Laravel Zap. ```php use Zap\Facades\Zap; // 1. Set up doctor's office hours Zap::for($doctor) ->named('Office Hours') ->availability() ->forYear(2025) ->weekly(['monday', 'tuesday', 'wednesday', 'thursday', 'friday']) ->addPeriod('09:00', '12:00') ->addPeriod('14:00', '17:00') ->save(); // 2. Block lunch time Zap::for($doctor) ->named('Lunch Break') ->blocked() ->forYear(2025) ->weekly(['monday', 'tuesday', 'wednesday', 'thursday', 'friday']) ->addPeriod('12:00', '13:00') ->save(); // 3. Get available slots for booking $slots = $doctor->getBookableSlots('2025-01-15', 60, 15); // 4. Check if specific time is available before booking if ($doctor->isBookableAtTime('2025-01-15', '10:00', '11:00')) { // Book the appointment Zap::for($doctor) ->named('Patient Consultation') ->appointment() ->from('2025-01-15') ->addPeriod('10:00', '11:00') ->withMetadata(['patient_id' => $patientId]) ->save(); } // 5. Find next available slot for a patient $nextSlot = $doctor->getNextBookableSlot(now()->format('Y-m-d'), 60); ``` -------------------------------- ### Setup and Test Laravel-Zap Source: https://github.com/ludoguenet/laravel-zap/blob/main/README.md Commands to clone the repository, install dependencies via Composer, and execute the test suite. ```bash git clone https://github.com/ludoguenet/laravel-zap.git cd laravel-zap composer install composer pest ``` -------------------------------- ### Real-World Example: Doctor Appointment System Source: https://github.com/ludoguenet/laravel-zap/blob/main/resources/boost/skills/zap-availability/SKILL.md Demonstrates a comprehensive example of setting up office hours, blocking time, getting available slots, and booking appointments using Laravel Zap. ```APIDOC ## Real-World Example: Doctor Appointment System ### Description Demonstrates a comprehensive example of setting up office hours, blocking time, getting available slots, and booking appointments using Laravel Zap. ### Steps 1. **Set up doctor's office hours**: Define recurring availability periods. 2. **Block lunch time**: Define recurring blocked periods. 3. **Get available slots for booking**: Retrieve bookable slots for a specific date. 4. **Check if specific time is available before booking**: Verify availability before creating an appointment. 5. **Find next available slot for a patient**: Find the nearest available slot. ### Request Example ```php use Zap\Facades\Zap; // 1. Set up doctor's office hours Zap::for($doctor) ->named('Office Hours') ->availability() ->forYear(2025) ->weekly(['monday', 'tuesday', 'wednesday', 'thursday', 'friday']) ->addPeriod('09:00', '12:00') ->addPeriod('14:00', '17:00') ->save(); // 2. Block lunch time Zap::for($doctor) ->named('Lunch Break') ->blocked() ->forYear(2025) ->weekly(['monday', 'tuesday', 'wednesday', 'thursday', 'friday']) ->addPeriod('12:00', '13:00') ->save(); // 3. Get available slots for booking $slots = $doctor->getBookableSlots('2025-01-15', 60, 15); // 4. Check if specific time is available before booking if ($doctor->isBookableAtTime('2025-01-15', '10:00', '11:00')) { // Book the appointment Zap::for($doctor) ->named('Patient Consultation') ->appointment() ->from('2025-01-15') ->addPeriod('10:00', '11:00') ->withMetadata(['patient_id' => $patientId]) ->save(); } // 5. Find next available slot for a patient $nextSlot = $doctor->getNextBookableSlot(now()->format('Y-m-d'), 60); ``` ``` -------------------------------- ### Install Laravel Zap Source: https://github.com/ludoguenet/laravel-zap/blob/main/resources/boost/skills/zap-schedules/SKILL.md Install the package via Composer, publish its assets, and run migrations. ```bash composer require laraveljutsu/zap php artisan vendor:publish --provider="Zap\ZapServiceProvider" php artisan migrate ``` -------------------------------- ### Install Laravel Zap Source: https://github.com/ludoguenet/laravel-zap/blob/main/README.md Install the package via Composer and publish the service provider configuration. ```bash composer require laraveljutsu/zap php artisan vendor:publish --provider="Zap\ZapServiceProvider" ``` -------------------------------- ### Set schedule start date Source: https://github.com/ludoguenet/laravel-zap/blob/main/_autodocs/schedule-builder.md Define the start date using either a string or a Carbon instance. ```php Zap::for($doctor)->from('2025-01-15'); Zap::for($doctor)->from(Carbon::parse('2025-01-15')); ``` -------------------------------- ### Configure Calendar Settings Source: https://github.com/ludoguenet/laravel-zap/blob/main/_autodocs/configuration.md Set the starting day of the week for calendar displays. ```php 'calendar' => [ 'week_start' => CarbonInterface::MONDAY, ], ``` -------------------------------- ### Get start datetime Source: https://github.com/ludoguenet/laravel-zap/blob/main/_autodocs/schedule-period-model.md Retrieves a Carbon instance representing the combined date and start_time. ```php public function getStartDateTimeAttribute(): CarbonInterface ``` ```php $period = SchedulePeriod::find(1); $startDateTime = $period->start_date_time; // Returns Carbon instance for "2025-01-15 09:00:00" ``` -------------------------------- ### Usage of findConflicts method Source: https://github.com/ludoguenet/laravel-zap/blob/main/_autodocs/events-and-services.md Example demonstrating how to resolve the service and retrieve conflicting schedules. ```php use Zap\/Services\/ConflictDetectionService; $conflictService = app(ConflictDetectionService::class); $schedule = Schedule::find(1); $conflicts = $conflictService->findConflicts($schedule); foreach ($conflicts as $conflict) { echo "Conflicts with: " . $conflict->name; } ``` -------------------------------- ### from(CarbonInterface|string $startDate) Source: https://github.com/ludoguenet/laravel-zap/blob/main/_autodocs/schedule-builder.md Sets the schedule start date. ```APIDOC ## from(CarbonInterface|string $startDate) ### Description Set the schedule start date. Can be a Carbon instance or date string (Y-m-d format). ### Signature `public function from(CarbonInterface|string $startDate): self` ### Parameters - **startDate** (CarbonInterface|string) - Required - Start date (Y-m-d format or Carbon instance) ### Returns `self` for method chaining ### Throws `InvalidArgumentException` if not set before `build()` or `save()` ``` -------------------------------- ### Creating Schedules Source: https://github.com/ludoguenet/laravel-zap/blob/main/resources/boost/skills/zap-schedules/SKILL.md Examples demonstrating how to create different types of schedules using the Zap facade or helper function with the fluent builder API. ```APIDOC ## Creating Schedules Use the `Zap` facade or `zap()` helper with the fluent builder: ```php use Zap\Facades\Zap; // Define availability (working hours) Zap::for($doctor) ->named('Office Hours') ->availability() ->forYear(2025) ->addPeriod('09:00', '12:00') ->addPeriod('14:00', '17:00') ->weekly(['monday', 'tuesday', 'wednesday', 'thursday', 'friday']) ->save(); // Block time (lunch break) Zap::for($doctor) ->named('Lunch Break') ->blocked() ->forYear(2025) ->addPeriod('12:00', '13:00') ->weekly(['monday', 'tuesday', 'wednesday', 'thursday', 'friday']) ->save(); // Create appointment Zap::for($doctor) ->named('Patient A - Consultation') ->appointment() ->from('2025-01-15') ->addPeriod('10:00', '11:00') ->withMetadata(['patient_id' => 1, 'type' => 'consultation']) ->save(); // Custom schedule with explicit overlap rules Zap::for($user) ->named('Custom Event') ->custom() ->from('2025-01-15') ->addPeriod('15:00', '16:00') ->noOverlap() ->save(); ``` Recurrence is set via methods such as `daily()`, `weekly(['monday', 'friday'])`, `monthly(['days_of_month' => [1, 15]])`, and **ordinal weekday**: `firstWednesdayOfMonth()`, `secondFridayOfMonth()`, `lastMondayOfMonth()` (see zap-recurrence skill for all patterns). ``` -------------------------------- ### Implement scheduling in a Controller using the Facade Source: https://github.com/ludoguenet/laravel-zap/blob/main/_autodocs/facade-and-helpers.md A practical example of handling availability and appointments within a controller using the Zap facade. ```php use Zap\Facades\Zap; use Zap\Enums\ScheduleTypes; class DoctorController { public function storeAvailability(Request $request) { $doctor = Doctor::find($request->doctor_id); try { $availability = Zap::for($doctor) ->named($request->name) ->availability() ->forYear($request->year) ->weekDays( $request->days, $request->start_time, $request->end_time ) ->save(); return response()->json(['schedule' => $availability], 201); } catch (\Zap\Exceptions\InvalidScheduleException $e) { return response()->json(['error' => $e->getMessage()], 422); } } public function bookAppointment(Request $request) { $doctor = Doctor::find($request->doctor_id); try { // Check if bookable first if (!$doctor->isBookableAtTime($request->date, $request->start_time, $request->end_time)) { return response()->json(['error' => 'Time not available'], 409); } $appointment = Zap::for($doctor) ->named("Patient: {$request->patient_name}") ->appointment() ->from($request->date) ->addPeriod($request->start_time, $request->end_time) ->withMetadata(['patient_id' => $request->patient_id]) ->save(); return response()->json(['appointment' => $appointment], 201); } catch (\Zap\Exceptions\ScheduleConflictException $e) { $nextSlot = $doctor->getNextBookableSlot($request->date); return response()->json([ 'error' => 'Time slot not available', 'next_available' => $nextSlot, ], 409); } } } ``` -------------------------------- ### Doctor availability and appointment management Source: https://github.com/ludoguenet/laravel-zap/blob/main/README.md Example of setting up office hours, lunch breaks, and patient appointments for a doctor model. ```php Zap::for($doctor)->named('Office Hours')->availability()->forYear(2025) ->addPeriod('09:00', '12:00')->addPeriod('14:00', '17:00') ->weekly(['monday', 'tuesday', 'wednesday', 'thursday', 'friday'])->save(); Zap::for($doctor)->named('Lunch Break')->blocked()->forYear(2025) ->addPeriod('12:00', '13:00') ->weekly(['monday', 'tuesday', 'wednesday', 'thursday', 'friday'])->save(); Zap::for($doctor)->named('Patient A - Checkup')->appointment() ->from('2025-01-15')->addPeriod('10:00', '11:00')->withMetadata(['patient_id' => 1])->save(); $slots = $doctor->getBookableSlots('2025-01-15', 60, 15); ``` -------------------------------- ### Query SchedulePeriods Source: https://github.com/ludoguenet/laravel-zap/blob/main/_autodocs/schedule-period-model.md Examples of filtering periods by date, time range, or availability. ```php // Find all periods on a specific date $periods = SchedulePeriod::forDate('2025-01-15')->get(); // Find periods overlapping with a time window $conflicts = SchedulePeriod::overlapping('2025-01-15', '10:00', '11:00')->get(); // Available periods in morning hours $morningAvailable = SchedulePeriod::available() ->forDate('2025-01-15') ->forTimeRange('09:00', '12:00') ->get(); ``` -------------------------------- ### Create Custom Schedules Source: https://github.com/ludoguenet/laravel-zap/blob/main/README.md Example of defining a custom event schedule with specific time periods and overlap rules. ```php Zap::for($user)->named('Custom Event')->custom() ->from('2025-01-15')->addPeriod('15:00', '16:00')->noOverlap()->save(); ``` -------------------------------- ### Retrieve Configuration Class Source: https://github.com/ludoguenet/laravel-zap/blob/main/_autodocs/enums-and-types.md Get the fully qualified class name for a frequency's configuration and instantiate it. ```php public function configClass(): string ``` ```php $frequency = Frequency::WEEKLY; $configClass = $frequency->configClass(); // Returns 'Zap\Data\WeeklyFrequencyConfig\WeeklyFrequencyConfig' $config = new $configClass(['days' => ['monday', 'friday']]); ``` -------------------------------- ### Define Date Ranges Source: https://github.com/ludoguenet/laravel-zap/blob/main/README.md Sets start and end boundaries for scheduled tasks. ```php $schedule->from('2025-01-15'); // Start $schedule->on('2025-01-15'); // Alias for from() $schedule->from('2025-01-01')->to('2025-12-31'); // Range $schedule->between('2025-01-01', '2025-12-31'); // Same $schedule->forYear(2025); // Full year ``` -------------------------------- ### Listen for ScheduleCreated Events Source: https://github.com/ludoguenet/laravel-zap/blob/main/_autodocs/events-and-services.md Example of using a closure to listen for schedule creation events to perform logging, dispatch notifications, or clear cache. ```php use Zap"=>"Events\\ScheduleCreated; use Illuminate\\Events\\Dispatcher; // In a service provider or event listener class Event::listen(ScheduleCreated::class, function (ScheduleCreated $event) { $schedule = $event->schedule; // Log the creation Log::info("Schedule created: {$schedule->name}", [ 'schedule_id' => $schedule->id, 'schedulable' => "{$schedule->schedulable_type}:{$schedule->schedulable_id}", 'type' => $schedule->schedule_type->value, ]); // Trigger workflow (email notification, etc.) dispatch(new SendScheduleNotification($schedule)); // Update related data Cache::forget("schedules:{$schedule->schedulable_id}"); }); ``` -------------------------------- ### Employee shift and vacation scheduling Source: https://github.com/ludoguenet/laravel-zap/blob/main/README.md Example of setting up regular work shifts and blocking out vacation time for an employee. ```php Zap::for($employee)->named('Regular Shift')->availability() ->weekDays(['monday', 'tuesday', 'wednesday', 'thursday', 'friday'], '09:00', '17:00') ->forYear(2025)->save(); Zap::for($employee)->named('Vacation Leave')->blocked() ->between('2025-06-01', '2025-06-15')->addPeriod('00:00', '23:59')->save(); ``` -------------------------------- ### Bi-Weekly Frequency Configuration Source: https://github.com/ludoguenet/laravel-zap/blob/main/_autodocs/enums-and-types.md Configures recurrence every two weeks with an optional start date. ```php use Zap\Data\WeeklyFrequencyConfig\BiWeeklyFrequencyConfig; Zap::for($model) ->biweekly(['monday', 'friday'], '2025-01-07') ->save(); ``` ```php [ 'days' => ['monday', 'friday'], 'startsOn' => '2025-01-07' // Optional: defines the biweekly cycle ] ``` -------------------------------- ### Find Next Available Source: https://github.com/ludoguenet/laravel-zap/blob/main/_autodocs/README.md Calculates the next available time slot starting from a given date. ```php $nextSlot = $doctor->getNextBookableSlot('2025-01-15'); echo "{$nextSlot['date']} at {$nextSlot['start_time']}"; ``` -------------------------------- ### Get availability periods for a date Source: https://github.com/ludoguenet/laravel-zap/blob/main/_autodocs/has-schedules-trait.md Retrieves all availability periods for a specific date using an optimized query. ```php protected function getAvailabilityPeriodsForDate(string $date): Collection ``` -------------------------------- ### Working with FrequencyConfig Source: https://github.com/ludoguenet/laravel-zap/blob/main/_autodocs/enums-and-types.md Illustrates creating a configuration instance and calculating recurrence dates. ```php use Zap\Data\WeeklyFrequencyConfig\WeeklyFrequencyConfig; $config = WeeklyFrequencyConfig::fromArray([ 'days' => ['monday', 'wednesday', 'friday'], ]); // Check if instance should be created for a date $date = Carbon::parse('2025-01-15'); if ($config->shouldCreateInstance($date)) { // This date has a recurring instance } // Get next recurrence $nextDate = $config->getNextRecurrence($date); ``` -------------------------------- ### Run Migrations Source: https://github.com/ludoguenet/laravel-zap/blob/main/README.md Execute the package migrations to set up the necessary database tables. ```bash php artisan migrate ``` -------------------------------- ### Quarterly Recurrence Configuration Source: https://github.com/ludoguenet/laravel-zap/blob/main/resources/boost/skills/zap-recurrence/SKILL.md Set up quarterly recurring events, defining specific days of the month and a starting month. Ideal for events happening every three months. ```php Zap::for($resource) ->named('Quarterly Review') ->appointment() ->quarterly([ 'days_of_month' => [7, 21], 'start_month' => 2 ]) ->from('2025-02-15') ->to('2025-11-15') ->addPeriod('09:00', '12:00') ->save(); ``` -------------------------------- ### Get Bookable Slots for a Date Source: https://github.com/ludoguenet/laravel-zap/blob/main/resources/boost/skills/zap-availability/SKILL.md Retrieve all bookable slots for a specific date, including slot duration and buffer time. The output details each slot's start and end time, and availability status. ```php // Get all bookable slots for a date // Parameters: date, slot duration (minutes), buffer (minutes) $slots = $doctor->getBookableSlots('2025-01-15', 60, 15); // Returns array of slots: // [ // ['start_time' => '09:00', 'end_time' => '10:00', 'is_available' => true, 'buffer_minutes' => 15], // ['start_time' => '10:15', 'end_time' => '11:15', 'is_available' => false, 'buffer_minutes' => 15], // ... // ] ``` -------------------------------- ### Annual Recurrence Configuration Source: https://github.com/ludoguenet/laravel-zap/blob/main/resources/boost/skills/zap-recurrence/SKILL.md Set up annual recurring events, defining specific days of the month and a start month. This is for events that happen once per year. ```php Zap::for($resource) ->named('Annual Conference') ->blocked() ->annually([ 'days_of_month' => [1, 15], 'start_month' => 4 ]) ->from('2025-04-01') ->to('2026-04-01') ->addPeriod('09:00', '18:00') ->save(); ``` -------------------------------- ### between(CarbonInterface|string $start, CarbonInterface|string $end) Source: https://github.com/ludoguenet/laravel-zap/blob/main/_autodocs/schedule-builder.md Sets both start and end dates in one call. ```APIDOC ## between(CarbonInterface|string $start, CarbonInterface|string $end) ### Description Set both start and end dates in one call. ### Signature `public function between(CarbonInterface|string $start, CarbonInterface|string $end): self` ### Parameters - **start** (CarbonInterface|string) - Required - Start date - **end** (CarbonInterface|string) - Required - End date ### Returns `self` for method chaining ``` -------------------------------- ### Compare access methods for ScheduleService Source: https://github.com/ludoguenet/laravel-zap/blob/main/_autodocs/facade-and-helpers.md Demonstrates the four equivalent ways to access the scheduling functionality. ```php use Zap\Facades\Zap; use Zap\Services\ScheduleService; // 1. Using Facade (static) Zap::for($doctor)->named('...')->save(); // 2. Using helper function zap()->for($doctor)->named('...')->save(); // 3. Using service directly app(ScheduleService::class)->for($doctor)->named('...')->save(); // 4. Using container alias app('zap')->for($doctor)->named('...')->save(); ``` -------------------------------- ### Dynamic Monthly Recurrence (4, 5, 7-11 months) Source: https://github.com/ludoguenet/laravel-zap/blob/main/resources/boost/skills/zap-recurrence/SKILL.md Configure dynamic monthly frequencies for intervals not covered by standard methods (4, 5, 7-11 months) using `everyXMonths`. You can specify days of the month and a start month. ```php Zap::for($resource) ->named('Quadrimester Review') ->appointment() ->everyFourMonths(['day_of_month' => 15]) ->forYear(2025) ->addPeriod('09:00', '12:00') ->save(); ``` ```php Zap::for($resource) ->named('Five-Month Cycle') ->appointment() ->everyFiveMonths([ 'days_of_month' => [1, 15], 'start_month' => 2 ]) ->forYear(2025) ->addPeriod('10:00', '11:00') ->save(); ``` ```php Zap::for($resource) ->named('Seven-Month Audit') ->appointment() ->everySevenMonths(['days_of_month' => [10]]) ->forYear(2025) ->addPeriod('14:00', '16:00') ->save(); ``` -------------------------------- ### Configuring PhpStorm IDE Hints Source: https://github.com/ludoguenet/laravel-zap/blob/main/_autodocs/facade-and-helpers.md Add facade hints to your IDE configuration to enable method autocomplete. ```xml // In your IDE config or phpsorm.xml ``` -------------------------------- ### Find Next Available Slot Source: https://github.com/ludoguenet/laravel-zap/blob/main/resources/boost/skills/zap-availability/SKILL.md Find the next available bookable slot starting from a specified date. The search extends up to 365 days into the future. You can also start the search from the current date by passing null. ```php // Find the next available slot starting from a date $nextSlot = $doctor->getNextBookableSlot('2025-01-15', 60, 15); // Returns: ['start_time' => '09:00', 'end_time' => '10:00', 'is_available' => true, 'date' => '2025-01-15', 'buffer_minutes' => 15] // Start from today $nextSlot = $doctor->getNextBookableSlot(null, 60); ``` -------------------------------- ### Define Bi-Weekly Recurrence Source: https://github.com/ludoguenet/laravel-zap/blob/main/_autodocs/quick-start-reference.md Sets a bi-weekly schedule starting from a specific date. ```php Zap::for($model) ->biweekly(['tuesday', 'thursday'], '2025-01-07') ->from('2025-01-07') ->to('2025-03-31') ->save(); ``` -------------------------------- ### Testing Zap with Facades and Integration Source: https://github.com/ludoguenet/laravel-zap/blob/main/_autodocs/facade-and-helpers.md Demonstrates mocking the Zap facade for unit tests and executing a full integration test using the service. ```php use Zap\Facades\Zap; use Zap\Models\Schedule; class ScheduleTest extends TestCase { public function test_can_create_schedule() { $doctor = Doctor::factory()->create(); Zap::shouldReceive('for') ->with($doctor) ->andReturnSelf(); Zap::shouldReceive('named') ->with('Office Hours') ->andReturnSelf(); // ... more mock setup } // Or use the real service for integration tests public function test_schedule_integration() { $doctor = Doctor::factory()->create(); $schedule = Zap::for($doctor) ->named('Office Hours') ->availability() ->forYear(2025) ->addPeriod('09:00', '17:00') ->save(); $this->assertDatabaseHas('schedules', [ 'name' => 'Office Hours', 'schedulable_id' => $doctor->id, ]); } } ``` -------------------------------- ### Create and Check Conflicts Workflow Source: https://github.com/ludoguenet/laravel-zap/blob/main/_autodocs/schedule-service.md Demonstrates creating office hours and appointments, then checking for scheduling conflicts. ```php $doctor = Doctor::find(1); $service = app(ScheduleService::class); // Create office hours $office = $service->create( $doctor, [ 'name' => 'Office Hours', 'schedule_type' => 'availability', 'start_date' => '2025-01-01', 'end_date' => '2025-12-31', 'is_recurring' => true, 'frequency' => 'weekly', 'frequency_config' => ['days' => ['monday', 'friday']], ], [['start_time' => '09:00', 'end_time' => '17:00', 'date' => '2025-01-01']], ); // Create appointment $appointment = $service->create( $doctor, [ 'name' => 'Patient: John Doe', 'schedule_type' => 'appointment', 'start_date' => '2025-01-15', 'end_date' => '2025-01-15', ], [['start_time' => '10:00', 'end_time' => '11:00', 'date' => '2025-01-15']], ); // Check if a new time would conflict $proposedAppointment = new Schedule([ 'name' => 'Patient: Jane Doe', 'schedule_type' => 'appointment', 'start_date' => '2025-01-15', 'end_date' => '2025-01-15', 'schedulable_type' => $doctor->getMorphClass(), 'schedulable_id' => $doctor->id, ]); $proposedAppointment->periods()->fill([ ['start_time' => '10:30', 'end_time' => '11:30', 'schedule_id' => $proposedAppointment->id, 'date' => '2025-01-15'], ]); if ($service->hasConflicts($proposedAppointment)) { $conflicts = $service->findConflicts($proposedAppointment); echo "Would conflict with: " . $conflicts[0]->name; } else { $saved = $service->create($doctor, $proposedAppointment->getAttributes(), ...); } ``` -------------------------------- ### Get Available Slots Source: https://github.com/ludoguenet/laravel-zap/blob/main/_autodocs/quick-start-reference.md Retrieve and filter bookable slots for a specific date. ```php $slots = $doctor->getBookableSlots($date, 60, 15); $available = array_filter($slots, fn($s) => $s['is_available']); return response()->json([ 'date' => $date, 'available_slots' => $available, ]); ``` -------------------------------- ### Using Frequency Enum Source: https://github.com/ludoguenet/laravel-zap/blob/main/_autodocs/enums-and-types.md Shows how to retrieve configuration classes and iterate through weekly frequencies. ```php use Zap\Enums\Frequency; $frequency = Frequency::WEEKLY; $configClass = $frequency->configClass(); $config = new $configClass(['days' => ['monday', 'friday']]); // All weekly frequencies $weeklyTypes = Frequency::weeklyFrequencies(); foreach ($weeklyTypes as $freq) { echo $freq->value; } ``` -------------------------------- ### Get end datetime Source: https://github.com/ludoguenet/laravel-zap/blob/main/_autodocs/schedule-period-model.md Retrieves a Carbon instance representing the combined date and end_time. ```php public function getEndDateTimeAttribute(): CarbonInterface ``` ```php $period = SchedulePeriod::find(1); $endDateTime = $period->end_date_time; // Returns Carbon instance for "2025-01-15 10:00:00" ``` -------------------------------- ### Create a SchedulePeriod Source: https://github.com/ludoguenet/laravel-zap/blob/main/_autodocs/schedule-period-model.md Demonstrates creating a new period using mass assignment. ```php use Zap\Models\SchedulePeriod; $period = SchedulePeriod::create([ 'schedule_id' => 1, 'date' => '2025-01-15', 'start_time' => '09:00', 'end_time' => '10:00', 'is_available' => true, ]); ``` -------------------------------- ### Set schedule date range Source: https://github.com/ludoguenet/laravel-zap/blob/main/_autodocs/schedule-builder.md Define both the start and end dates in a single method call. ```php Zap::for($doctor)->between('2025-01-01', '2025-12-31'); ``` -------------------------------- ### Use the zap() helper function Source: https://github.com/ludoguenet/laravel-zap/blob/main/_autodocs/facade-and-helpers.md The helper returns the service instance, allowing for fluent method chaining and conflict checking. ```php // Using the helper instead of the facade zap()->for($doctor) ->named('Office Hours') ->availability() ->forYear(2025) ->save(); // Check conflicts if (zap()->hasConflicts($schedule)) { // Handle conflict } // Find conflicts $conflicts = zap()->findConflicts($schedule); ``` -------------------------------- ### Creating a Schedule with for() Source: https://github.com/ludoguenet/laravel-zap/blob/main/_autodocs/facade-and-helpers.md Initializes a schedule builder for a specific model instance. ```php static function for(Model $schedulable): ScheduleBuilder ``` ```php use Zap\Facades\Zap; $doctor = Doctor::find(1); $schedule = Zap::for($doctor) ->named('Office Hours') ->availability() ->forYear(2025) ->addPeriod('09:00', '17:00') ->weekly(['monday', 'friday']) ->save(); ``` -------------------------------- ### Configure Environment Variables Source: https://github.com/ludoguenet/laravel-zap/blob/main/_autodocs/configuration.md Manage global package settings using environment variables within the configuration file. ```php // config/zap.php return [ 'conflict_detection' => [ 'enabled' => env('ZAP_CONFLICT_DETECTION_ENABLED', true), 'buffer_minutes' => env('ZAP_BUFFER_MINUTES', 0), ], 'validation' => [ 'require_future_dates' => env('ZAP_REQUIRE_FUTURE_DATES', true), 'max_date_range' => env('ZAP_MAX_DATE_RANGE', 365), ], ]; ``` ```text ZAP_CONFLICT_DETECTION_ENABLED=true ZAP_BUFFER_MINUTES=15 ZAP_REQUIRE_FUTURE_DATES=false ZAP_MAX_DATE_RANGE=730 ``` -------------------------------- ### on(CarbonInterface|string $startDate) Source: https://github.com/ludoguenet/laravel-zap/blob/main/_autodocs/schedule-builder.md Alias for from(). ```APIDOC ## on(CarbonInterface|string $startDate) ### Description Alias for `from()`. Set the schedule start date. ### Signature `public function on(CarbonInterface|string $startDate): self` ``` -------------------------------- ### Meeting room scheduling Source: https://github.com/ludoguenet/laravel-zap/blob/main/README.md Example of defining recurring availability and specific appointments for a meeting room. ```php Zap::for($room)->named('Conference Room A')->availability() ->weekDays(['monday', 'tuesday', 'wednesday', 'thursday', 'friday'], '08:00', '18:00') ->forYear(2025)->save(); Zap::for($room)->named('Board Meeting')->appointment() ->from('2025-03-15')->addPeriod('09:00', '11:00') ->withMetadata(['organizer' => 'john@company.com'])->save(); ``` -------------------------------- ### Get total duration Source: https://github.com/ludoguenet/laravel-zap/blob/main/_autodocs/schedule-model.md Calculates the total duration of all periods in minutes, accessible as a model property. ```php public function getTotalDurationAttribute(): int ``` ```php $schedule = Schedule::find(1); $totalMinutes = $schedule->total_duration; // Accessed as property ``` -------------------------------- ### Accessing Zap Facade Methods Source: https://github.com/ludoguenet/laravel-zap/blob/main/_autodocs/facade-and-helpers.md Demonstrates static access to the ScheduleService via the Zap facade. ```php use Zap\Facades\Zap; // Static facade calls Zap::for($model)->named('...'); Zap::findConflicts($schedule); Zap::hasConflicts($schedule); ``` -------------------------------- ### Setup HasSchedules Trait Source: https://github.com/ludoguenet/laravel-zap/blob/main/_autodocs/has-schedules-trait.md Apply the HasSchedules trait to an Eloquent model to enable scheduling functionality. ```php use Illuminate\Database\Eloquent\Model; use Zap\Models\Concerns\HasSchedules; class Doctor extends Model { use HasSchedules; } ``` -------------------------------- ### Retrieve Schedule Attributes Source: https://github.com/ludoguenet/laravel-zap/blob/main/_autodocs/schedule-builder.md Returns an array containing schedule metadata such as name, start date, and frequency. ```php public function getAttributes(): array ``` -------------------------------- ### Find Next Available Slot Source: https://github.com/ludoguenet/laravel-zap/blob/main/resources/boost/skills/zap-availability/SKILL.md Finds the next available bookable slot starting from a specified date. ```APIDOC ## Find Next Available Slot ### Description Finds the next available bookable slot starting from a specified date. The method searches up to 365 days in the future. ### Method Signature `getNextBookableSlot(?string $startDate, int $slotDurationMinutes, ?int $bufferMinutes = null): ?array` ### Parameters #### Path Parameters - **start_date** (string|null) - Optional - The date to start searching from (e.g., 'YYYY-MM-DD'). If null, searches from the current date. - **slot_duration_minutes** (int) - Required - The desired duration of the slot in minutes. - **buffer_minutes** (int) - Optional - The buffer time in minutes between slots. ### Response Example ```json {'start_time': '09:00', 'end_time': '10:00', 'is_available': true, 'date': '2025-01-15', 'buffer_minutes': 15} ``` ### Request Example ```php // Find the next available slot starting from a date $nextSlot = $doctor->getNextBookableSlot('2025-01-15', 60, 15); // Start from today $nextSlot = $doctor->getNextBookableSlot(null, 60); ``` ``` -------------------------------- ### Initialize ScheduleService Constructor Source: https://github.com/ludoguenet/laravel-zap/blob/main/_autodocs/schedule-service.md The service is typically resolved via the Laravel container using the 'zap' alias or the ScheduleService class. ```php public function __construct( private ValidationService $validator, private ConflictDetectionService $conflictService, private ?string $scheduleClass ) ``` -------------------------------- ### daily() Source: https://github.com/ludoguenet/laravel-zap/blob/main/_autodocs/schedule-builder.md Creates a schedule that recurs every day. ```APIDOC ## daily() ### Description Creates a schedule that recurs every day. ### Signature `public function daily(): self` ### Returns `self` for method chaining. ``` -------------------------------- ### Configure Room Availability and Book Meetings with Zap Source: https://github.com/ludoguenet/laravel-zap/blob/main/resources/boost/skills/zap-availability/SKILL.md Use Zap::for() to define resources like rooms and then chain methods to set availability or book appointments. Availability can be set for specific weekdays and time ranges for a given year. Appointments can include metadata. ```php Zap::for($room) ->named('Conference Room A') ->availability() ->weekDays(['monday', 'tuesday', 'wednesday', 'thursday', 'friday'], '08:00', '18:00') ->forYear(2025) ->save(); ``` ```php $slots = $room->getBookableSlots('2025-03-15', 60); ``` ```php Zap::for($room) ->named('Board Meeting') ->appointment() ->from('2025-03-15') ->addPeriod('09:00', '11:00') ->withMetadata(['organizer' => 'john@company.com']) ->save(); ``` -------------------------------- ### Retrieve bookable slots Source: https://github.com/ludoguenet/laravel-zap/blob/main/_autodocs/has-schedules-trait.md Get an array of all bookable time slots for a specific date using getBookableSlots. ```php $doctor = Doctor::find(1); $slots = $doctor->getBookableSlots('2025-01-15', 60, 15); // Output: [ ['start_time' => '09:00', 'end_time' => '10:00', 'is_available' => true, 'buffer_minutes' => 15], ['start_time' => '10:15', 'end_time' => '11:15', 'is_available' => false, 'buffer_minutes' => 15], ['start_time' => '11:30', 'end_time' => '12:30', 'is_available' => true, 'buffer_minutes' => 15], ] ``` -------------------------------- ### Implement Room Booking System Source: https://github.com/ludoguenet/laravel-zap/blob/main/_autodocs/quick-start-reference.md Manage room availability, maintenance windows, and retrieve bookable slots. ```php // Room always available Zap::for($room)->named('Room Available')->availability() ->daily()->from('2025-01-01')->to('2025-12-31')->save(); // Maintenance window Zap::for($room)->named('Maintenance')->blocked() ->from('2025-07-15')->to('2025-07-20')->save(); // Get available slots $slots = $room->getBookableSlots($date, 120, 15); // 2-hour slots, 15-min buffer ``` -------------------------------- ### Get Available Slots Source: https://github.com/ludoguenet/laravel-zap/blob/main/_autodocs/README.md Retrieves an array of available time slots based on duration and buffer requirements. ```php $slots = $doctor->getBookableSlots('2025-01-15', 60, 15); // Returns array of 60-minute slots with 15-minute buffer ``` -------------------------------- ### Configure Conflict Detection Source: https://github.com/ludoguenet/laravel-zap/blob/main/_autodocs/README.md Settings for enabling conflict detection and defining buffer times. ```php 'conflict_detection' => [ 'enabled' => true, 'buffer_minutes' => 0, ] ``` -------------------------------- ### Get Total Scheduled Time Source: https://github.com/ludoguenet/laravel-zap/blob/main/resources/boost/skills/zap-availability/SKILL.md Calculates the total scheduled time in minutes for a given date range. ```APIDOC ## Total Scheduled Time ### Description Calculates the total scheduled time in minutes for a given date range. ### Method Signature `getTotalScheduledTime(string $startDate, string $endDate): int` ### Parameters #### Path Parameters - **start_date** (string) - Required - The start date of the range (e.g., 'YYYY-MM-DD'). - **end_date** (string) - Required - The end date of the range (e.g., 'YYYY-MM-DD'). ### Request Example ```php // Get total scheduled time in minutes for a date range $totalMinutes = $doctor->getTotalScheduledTime('2025-01-01', '2025-12-31'); ``` ``` -------------------------------- ### Zap::schedule() Source: https://github.com/ludoguenet/laravel-zap/blob/main/_autodocs/facade-and-helpers.md Creates a new, uninitialized schedule builder. ```APIDOC ## Zap::schedule() ### Description Create a new schedule builder without a schedulable. Note that for() must be called before saving. ### Returns - **ScheduleBuilder** - Uninitialized builder instance. ``` -------------------------------- ### Restrict schedule to working hours Source: https://github.com/ludoguenet/laravel-zap/blob/main/_autodocs/schedule-builder.md Limits the schedule to a specific time range defined by start and end strings. ```php public function workingHoursOnly(string $start = '09:00', string $end = '17:00'): self ``` -------------------------------- ### Filter periods by time range Source: https://github.com/ludoguenet/laravel-zap/blob/main/_autodocs/schedule-period-model.md Retrieve periods that fall within a specified start and end time range. ```php public static function forTimeRange(string $startTime, string $endTime): Builder ``` ```php $morningPeriods = SchedulePeriod::forTimeRange('09:00', '12:00')->get(); ``` -------------------------------- ### Using the Zap Facade Source: https://github.com/ludoguenet/laravel-zap/blob/main/_autodocs/schedule-service.md Utilizes the Zap facade for a fluent interface to create schedules and check for conflicts. ```php use Zap\Facades\Zap; $doctor = Doctor::find(1); // Create with fluent interface $schedule = Zap::for($doctor) ->named('Office Hours') ->availability() ->forYear(2025) ->weekDays(['monday', 'tuesday', 'wednesday', 'thursday', 'friday'], '09:00', '17:00') ->save(); // Check for conflicts with another schedule $conflicts = Zap::findConflicts($schedule); if (Zap::hasConflicts($schedule)) { echo "Schedule has conflicts"; } ``` -------------------------------- ### Create and Query Schedules Source: https://github.com/ludoguenet/laravel-zap/blob/main/_autodocs/has-schedules-trait.md Define availability and blocked periods for a model, then retrieve schedules for a specific date. ```php $doctor = Doctor::find(1); // Create availability $availability = $doctor->createSchedule() ->named('Office Hours') ->availability() ->forYear(2025) ->weekDays(['monday', 'tuesday', 'wednesday', 'thursday', 'friday'], '09:00', '17:00') ->save(); // Create a block (lunch) $lunch = $doctor->createSchedule() ->named('Lunch Break') ->blocked() ->forYear(2025) ->weekly(['monday', 'tuesday', 'wednesday', 'thursday', 'friday']) ->addPeriod('12:00', '13:00') ->save(); // Get availability for a date $schedules = $doctor->schedulesForDate('2025-01-15')->get(); ``` -------------------------------- ### Filter Schedules by Date Range Source: https://github.com/ludoguenet/laravel-zap/blob/main/_autodocs/schedule-model.md Filters schedules active within a specified start and end date range. ```php $schedules = Schedule::forDateRange('2025-01-01', '2025-01-31')->get(); ``` -------------------------------- ### Get duration in minutes Source: https://github.com/ludoguenet/laravel-zap/blob/main/_autodocs/schedule-period-model.md Access the duration of the period in minutes as a property. Returns 0 if start_time or end_time is missing. ```php public function getDurationMinutesAttribute(): int ``` ```php $period = SchedulePeriod::find(1); $minutes = $period->duration_minutes; // Accessed as property // Returns 60 if period is 09:00-10:00 ``` -------------------------------- ### Initialize ScheduleBuilder with schedule() Source: https://github.com/ludoguenet/laravel-zap/blob/main/_autodocs/schedule-service.md Creates an uninitialized ScheduleBuilder. The for() method must be called on the builder instance before proceeding with configuration. ```php public function schedule(): ScheduleBuilder ``` ```php $builder = zap()->schedule(); $builder->for($doctor)->named('...'); ``` -------------------------------- ### Get Bookable Slots Source: https://github.com/ludoguenet/laravel-zap/blob/main/resources/boost/skills/zap-availability/SKILL.md Retrieves all bookable slots for a given date, including slot duration and buffer time. ```APIDOC ## Get Bookable Slots ### Description Retrieves all bookable slots for a given date, including slot duration and buffer time. ### Method Signature `getBookableSlots(string $date, int $slotDurationMinutes, int $bufferMinutes): array` ### Parameters #### Path Parameters - **date** (string) - Required - The date to retrieve slots for (e.g., 'YYYY-MM-DD'). - **slot_duration_minutes** (int) - Required - The desired duration of each slot in minutes. - **buffer_minutes** (int) - Required - The buffer time in minutes between slots. ### Response Example ```json [ {'start_time': '09:00', 'end_time': '10:00', 'is_available': true, 'buffer_minutes': 15}, {'start_time': '10:15', 'end_time': '11:15', 'is_available': false, 'buffer_minutes': 15}, ... ] ``` ### Request Example ```php // Get all bookable slots for a date // Parameters: date, slot duration (minutes), buffer (minutes) $slots = $doctor->getBookableSlots('2025-01-15', 60, 15); ``` ``` -------------------------------- ### Perform recurring scheduling tasks with the helper Source: https://github.com/ludoguenet/laravel-zap/blob/main/_autodocs/facade-and-helpers.md Demonstrates using the zap() helper to batch process recurring schedules for multiple entities. ```php // In a command or controller public function setupRecurringSchedules() { $rooms = Room::all(); foreach ($rooms as $room) { // Office hours zap()->for($room) ->named('Office Hours') ->availability() ->forYear(2025) ->weekDays(['monday', 'tuesday', 'wednesday', 'thursday', 'friday'], '08:00', '18:00') ->save(); // Lunch closure zap()->for($room) ->named('Lunch Closure') ->blocked() ->forYear(2025) ->weekly(['monday', 'tuesday', 'wednesday', 'thursday', 'friday']) ->addPeriod('12:00', '13:00') ->save(); } } ``` -------------------------------- ### Check if period is active Source: https://github.com/ludoguenet/laravel-zap/blob/main/_autodocs/schedule-period-model.md Verifies if the current system time falls within the period's start and end datetimes. ```php public function isActiveNow(): bool ``` ```php $period = SchedulePeriod::find(1); if ($period->isActiveNow()) { // Period is currently active } ``` -------------------------------- ### Retrieve Period Configurations Source: https://github.com/ludoguenet/laravel-zap/blob/main/_autodocs/schedule-builder.md Returns an array of currently configured period settings. ```php public function getPeriods(): array ``` -------------------------------- ### Annual Recurrence Source: https://github.com/ludoguenet/laravel-zap/blob/main/resources/boost/skills/zap-recurrence/SKILL.md Sets up a recurrence that occurs once per year on specified days of the month, with an option to anchor the start month. ```APIDOC ## Annual Recurrence Once per year: ```php Zap::for($resource) ->named('Annual Conference') ->blocked() ->annually([ 'days_of_month' => [1, 15], 'start_month' => 4 ]) ->from('2025-04-01') ->to('2026-04-01') ->addPeriod('09:00', '18:00') ->save(); ``` ``` -------------------------------- ### Injecting Zap Services into a Class Source: https://github.com/ludoguenet/laravel-zap/blob/main/_autodocs/events-and-services.md Demonstrates constructor injection of ScheduleService, ValidationService, and ConflictDetectionService into a custom manager class. ```php use Zap\Services\ScheduleService; use Zap\Services\ValidationService; use Zap\Services\ConflictDetectionService; class MyScheduleManager { public function __construct( private ScheduleService $scheduleService, private ValidationService $validator, private ConflictDetectionService $conflictDetector, ) {} public function createSafeSchedule(Model $model, array $data): Schedule { // Validate first try { $this->validator->validate($model, $data['attributes'], $data['periods'] ?? []); } catch (InvalidScheduleException $e) { throw new Exception("Invalid schedule: " . $e->getMessage()); } // Create schedule (which includes conflict checking) try { return $this->scheduleService->create( $model, $data['attributes'], $data['periods'] ?? [], ); } catch (ScheduleConflictException $e) { throw new Exception("Schedule conflicts with existing schedules"); } } } ``` -------------------------------- ### Publish Configuration File Source: https://github.com/ludoguenet/laravel-zap/blob/main/_autodocs/configuration.md Command to generate the configuration file in your Laravel application. ```bash php artisan vendor:publish --tag=zap-config ``` -------------------------------- ### Define Time Periods for Schedule Source: https://github.com/ludoguenet/laravel-zap/blob/main/resources/boost/skills/zap-schedules/SKILL.md Add time periods to a schedule, either individually or as a list of start and end times. ```php // Single period $schedule->addPeriod('09:00', '17:00'); ``` ```php // Multiple periods (split shifts) $schedule->addPeriod('09:00', '12:00'); $schedule->addPeriod('14:00', '17:00'); ``` ```php // Multiple periods at once $schedule->addPeriods([ ['start_time' => '09:00', 'end_time' => '12:00'], ['start_time' => '14:00', 'end_time' => '17:00'], ]); ```