Dev.to · 4 min read

Book meetings in Laravel with Wireschedule

Book meetings in Laravel with Wireschedule

Sometimes you want your visitors to be able to book a call or a demo with you, and you might not want to pay for Calendy or to use external widgets. You might also want the booking data in your own database, not leaving for someone else's dashboard, and you want the booking to actually plug into your app's pipeline instead of being a dead-end iframe. Wireschedule is a self-hosted meeting scheduler for Laravel that does exactly that. Availability lives in config, bookings land in your own table, and the UI is a Livewire component you drop in. Here is the fast path to getting it running and wired into your own logic. How to install It is a normal Composer package, and the service provider registers its migration for you, so there is nothing to publish just to run it. composer require edulazaro/wireschedule php artisan migrate The only manual step is the stylesheet. Import it into your CSS bundle or the widget shows up unstyled. @import '../../vendor/edulazaro/wireschedule/resources/css/wireschedule.css'; There is no separate JS build. The Livewire view ships its own inline Alpine, so it uses the Livewire and Alpine you already have. Requirements are PHP 8.2+, Laravel 11+ and Livewire 3. How to use it Drop the Blade component wherever people should book. The event you pass is a key you will define in config in a second. Pick the look once on the root element. Wireschedule shares one theme attribute with the rest of the wire* family, and the CSS ships eleven themes including studio, minimal, brutalist, glass and neon. Now shape the demo event. Publish the config and open it up. php artisan vendor:publish --tag=wireschedule-config Each event is a weekly availability map plus a few booking rules. The map is keyed by ISO weekday, 1 for Monday through 7 for Sunday, and each day is a list of HH:MM ranges. duration and buffer are minutes, days_ahead is the booking horizon, and min_notice is the minimum minutes ahead someone can book. 'timezone' => 'Europe/Madrid', // organiser zone; availability is read here, stored UTC 'events' => [ 'demo' => [ 'label' => 'Demo', 'duration' => 30, 'buffer' => 0, 'days_ahead' => 21, 'min_notice' => 120, 'availability' => [ 1 => [['10:00', '14:00'], ['16:00', '18:00']], 5 => [['10:00', '14:00']], ], ], ], The component renders the available dates, the free slots for the selected date, and a short name and email form, saving a booking on confirm. Wiring the booking into your pipeline This is the part that makes it more than a form. After a successful save, the Scheduler dispatches a wireschedule-booked Livewire event carrying the new booking id. Listen for it in a parent Livewire component and fire whatever follow-up you need, like pinging your team channel or syncing a CRM. use Livewire\Attributes\On; class BookingPage extends Component { #[On('wireschedule-booked')] public function onBooked(int $id): void { // notify your team, push to a CRM, dispatch a job... } } Because the booking is a row in your database, you read it back with plain Eloquent. The model ships scopes so the common query stays short. use EduLazaro\WireSchedule\Models\Booking; Booking::ofType('demo')->confirmed()->upcoming()->orderBy('starts_at')->get(); If the person was logged in when they booked, Wireschedule captures them automatically through a polymorphic booker relation, so you can attribute the booking to an account with no extra work. For a guest it is just null. $booking->booker; // the authenticated user who booked, or null Timezones and double-booking are handled You do not have to think about either of these, which is half the reason to use it. The visitor's browser timezone is detected client side and used to display the slots, then everything is persisted in UTC with the visitor's zone stored on the row, so your availability config stays in your own timezone and the maths just works. Double-booking is blocked at two layers: a unique (event_type, starts_at) index on the table, plus a re-check that the slot is still free at confirm time, so two concurrent requests cannot grab the same slot. Good to know The event prop is locked, and on mount the component runs abort_unless against the event config. If you pass an event key that is not defined under wireschedule.events, the component 404s instead of rendering an empty widget. Just define the event in the config before you point the component at it and you are fine. 👉 Package on Packagist: https://packagist.org/packages/edulazaro/wireschedule 👉 Source on GitHub: https://github.com/edulazaro/wireschedule

This is a summary aggregated from Dev.to. Read the complete article on the original site:

Read full article at Dev.to

More Programming & Dev News