Weave 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

Wireschedule Laravel Package

edulazaro/wireschedule

Self-hosted Calendly alternative for Laravel: define availability per event in config, let visitors book free slots via a drop-in Livewire component, and keep bookings in your own database. Themeable, no third-party services.

View on GitHub
Deep Wiki
Context7

Getting Started

First Steps

  1. Installation

    composer require edulazaro/wireschedule
    php artisan vendor:publish --provider="Edulazaro\Wireschedule\WirescheduleServiceProvider" --tag="wireschedule-config"
    php artisan migrate
    
    • Publish the default config (config/wireschedule.php) and run migrations to set up the database tables.
  2. Basic Setup

    • Configure your availability in config/wireschedule.php:
      'availability' => [
          'timezone' => 'America/New_York',
          'default_duration' => 30, // minutes
          'slots_per_day' => 10,
          'working_days' => ['mon', 'tue', 'wed', 'thu', 'fri'],
      ],
      
    • Define your meeting types (e.g., "Consultation", "Demo") in the database via the MeetingType model or Tinker:
      php artisan tinker
      >>> \App\Models\MeetingType::create(['name' => 'Consultation', 'duration' => 60]);
      
  3. First Use Case: Embedding a Scheduler

    • Add the Livewire component to a Blade view:
      @livewire('wireschedule::scheduler', ['meeting_type_id' => 1])
      
    • This renders a themed calendar UI where users can book slots based on your configured availability.

Implementation Patterns

Core Workflows

  1. Config-Driven Availability

    • Use the config/wireschedule.php to define global availability rules (timezone, durations, working days).
    • Override per-meeting-type via the MeetingType model:
      class MeetingType extends Model {
          protected $casts = [
              'duration' => 'integer',
              'working_days' => 'array',
          ];
      }
      
    • Dynamically fetch availability in Livewire components:
      public function getAvailableSlots() {
          return \Edulazaro\Wireschedule\Models\Availability::where('meeting_type_id', $this->meeting_type_id)
              ->whereDate('date', '>=', now()->toDateString())
              ->get();
      }
      
  2. Livewire UI Integration

    • Extend the default scheduler with custom logic:
      use Livewire\Component;
      use Edulazaro\Wireschedule\Livewire\Scheduler;
      
      class CustomScheduler extends Scheduler {
          protected $rules = [
              'name' => 'required|min:3',
              'email' => 'required|email',
          ];
      
          public function submitForm() {
              $this->validate();
              // Custom logic (e.g., send notification)
              $this->dispatch('booking-submitted');
          }
      }
      
    • Reuse the wire* theme system (e.g., wiremodal for booking confirmations):
      @livewire('wireschedule::scheduler')
      @push('scripts')
          @wireScript('wireschedule::scheduler')
      @endpush
      
  3. Database-Driven Extensions

    • Add custom fields to bookings via migrations:
      php artisan make:migration add_custom_fields_to_bookings_table --table=bookings
      
    • Access them in Livewire:
      $booking->custom_field; // e.g., 'agenda_notes'
      
  4. API Access (Optional)

    • Expose endpoints for programmatic booking:
      Route::post('/api/book', [BookingController::class, 'store']);
      
    • Use the Booking model to create slots:
      $booking = \App\Models\Booking::create([
          'meeting_type_id' => 1,
          'user_id' => auth()->id(),
          'starts_at' => now()->addHours(2),
          'duration' => 60,
      ]);
      

Gotchas and Tips

Pitfalls

  1. Timezone Mismatches

    • Always ensure config/wireschedule.php and your Laravel APP_TIMEZONE match. Use Carbon::setTimezone() in queries if needed:
      $slots = Availability::where('date', '>=', now()->timezone('UTC')->toDateString())->get();
      
  2. Livewire Component Isolation

    • Avoid mixing wireschedule::scheduler with other Livewire components that modify the same DOM elements (e.g., conflicting IDs/classes).
  3. Database Conflicts

    • If using custom fields, ensure migrations run after wireschedule migrations to avoid constraint errors.
  4. Caching Availability

    • The package doesn’t cache availability by default. For high-traffic sites, cache slots:
      $slots = Cache::remember("availability_{$meeting_type_id}", now()->addHours(1), function () {
          return Availability::where(...)->get();
      });
      

Debugging Tips

  • Log Availability Queries:
    \DB::enableQueryLog();
    $slots = Availability::where(...)->get();
    \Log::info('Availability Query:', ['query' => \DB::getQueryLog()]);
    
  • Check Livewire Events: Use wire:ignore or wire:key to debug UI updates:
    <div wire:key="scheduler-{{ $meeting_type_id }}">
        @livewire('wireschedule::scheduler', ['meeting_type_id' => $meeting_type_id])
    </div>
    
  • Validate Config: Run php artisan wireschedule:validate-config (if the package includes this command) to catch misconfigurations early.

Extension Points

  1. Custom Booking Logic
    • Override the Booking model’s create method or use model events:
      \App\Models\Booking::created(function ($booking) {
          // Send Slack/email notification
      });
      
  2. Theme Overrides
    • Publish and modify the Livewire views:
      php artisan vendor:publish --tag=wireschedule-views
      
    • Extend the wire* theme classes (e.g., WireModal) in your assets:
      /* resources/css/wireschedule.css */
      .wire-scheduler .wire-modal { --modal-width: 500px; }
      
  3. Recurring Availability
    • Use Laravel’s Schedule facade to pre-generate slots:
      \Schedule::call(function () {
          \Edulazaro\Wireschedule\Jobs\GenerateAvailability::dispatch();
      })->daily();
      
  4. Multi-Tenant Support
    • Scope availability by tenant in the Availability model:
      protected static function booted() {
          static::addGlobalScope('tenant', function (Builder $builder) {
              $builder->where('tenant_id', \Tenant::current()->id);
          });
      }
      
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.
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels