承接 edissavov/filament-booking-calendar 相关项目开发

从需求分析到上线部署,全程专人跟进,保证项目质量与交付效率

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

edissavov/filament-booking-calendar

Composer 安装命令:

composer require edissavov/filament-booking-calendar

包简介

A flexible booking calendar widget for Filament v3 built on FullCalendar

README 文档

README

A flexible, feature-rich booking calendar widget for Filament v3 built on FullCalendar. Perfect for appointment scheduling, salon bookings, room reservations, and any booking-based system.

Features

  • 📅 Full CRUD operations on calendar events
  • 🎨 Status-based color coding (customizable)
  • 📱 Mobile-responsive design with auto-view switching
  • ⚙️ Highly configurable through config file
  • 🔧 Extensible through widget inheritance
  • 🌍 Multi-language support
  • ⏰ Configurable business hours and timezones
  • 📊 Multiple calendar views (Month, Week, Day, List)
  • 💡 Event tooltips
  • 🎯 Metadata support for domain-specific fields

Installation

Install the package via Composer:

composer require edissavov/filament-booking-calendar

Quick Start

1. Publish Configuration (Optional)

php artisan vendor:publish --tag=filament-booking-calendar-config

2. Run Migrations

If you don't have a bookings table:

php artisan vendor:publish --tag=filament-booking-calendar-migrations
php artisan migrate

Note: If you already have a bookings table, skip this step and configure your own model in the config file.

3. Register the Widget

Option A: As a Page Widget

Create a Filament page:

// app/Filament/Pages/Calendar.php
<?php

namespace App\Filament\Pages;

use Edissavov\FilamentBookingCalendar\Widgets\BookingCalendarWidget;
use Filament\Pages\Page;

class Calendar extends Page
{
    protected static ?string $navigationIcon = 'heroicon-o-calendar-days';
    protected static string $view = 'filament.pages.calendar';
    protected static ?string $title = 'Calendar';

    protected function getHeaderWidgets(): array
    {
        return [
            BookingCalendarWidget::class,
        ];
    }
}

Create the view:

{{-- resources/views/filament/pages/calendar.blade.php --}}
<x-filament-panels::page />

Option B: As a Dashboard Widget

Register in your Panel Provider:

// app/Providers/Filament/AdminPanelProvider.php
->widgets([
    \Edissavov\FilamentBookingCalendar\Widgets\BookingCalendarWidget::class,
])

Configuration

Using Existing Booking Model

If you already have a Booking model, point to it in the config:

// config/filament-booking-calendar.php
'models' => [
    'booking' => \App\Models\Booking::class,
],

Minimum required fields:

  • name (string)
  • phone (string)
  • email (string, nullable)
  • date (datetime)
  • status (string)
  • price (decimal, nullable)
  • notes (text, nullable)

Customize Status Colors

'statuses' => [
    'pending' => [
        'label' => 'Pending Confirmation',
        'color' => ['bg' => '#FFA500', 'border' => '#FF8C00'],
    ],
    'confirmed' => [
        'label' => 'Confirmed',
        'color' => ['bg' => '#3B82F6', 'border' => '#2563EB'],
    ],
    // Add more statuses...
],

Localization

'calendar' => [
    'locale' => 'bg',  // Bulgarian
    'timezone' => 'Europe/Sofia',
    'button_text' => [
        'today' => 'Днес',
        'month' => 'Месец',
        'week' => 'Седмица',
        'day' => 'Ден',
        'list_week' => 'Списък седмица',
        'list_day' => 'Списък ден',
    ],
],

Business Hours

'calendar' => [
    'business_hours' => [
        'start' => '09:00:00',
        'end' => '18:00:00',
    ],
],

Phone Number Formatting

'form' => [
    'enable_phone_formatting' => true,
    'phone_country_code' => '+359',  // Bulgaria
],

This will automatically convert phone numbers starting with "0" to "+359xxx".

Advanced Usage

Extending the Widget

For domain-specific customizations (like pet grooming), extend the widget:

// app/Filament/Widgets/PetGroomingCalendar.php
<?php

namespace App\Filament\Widgets;

use Edissavov\FilamentBookingCalendar\Widgets\BookingCalendarWidget;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\Fieldset;

class PetGroomingCalendar extends BookingCalendarWidget
{
    protected function getFormSchema(): array
    {
        $baseSchema = parent::getFormSchema();

        // Add pet-specific fields
        $petFields = Fieldset::make('Pet Information')
            ->schema([
                TextInput::make('metadata.pet_name')
                    ->label('Pet Name')
                    ->required(),
                TextInput::make('metadata.breed')
                    ->label('Breed'),
                Select::make('metadata.weight')
                    ->label('Weight')
                    ->options([
                        'Small (< 5kg)' => 'Small (< 5kg)',
                        'Medium (5-15kg)' => 'Medium (5-15kg)',
                        'Large (15-30kg)' => 'Large (15-30kg)',
                    ]),
            ])
            ->columns(3);

        // Insert after customer information
        array_splice($baseSchema, 1, 0, [$petFields]);

        return $baseSchema;
    }

    protected function getEventTitle($booking): string
    {
        $petName = $booking->metadata['pet_name'] ?? null;
        return $booking->name . ($petName ? " ($petName)" : '');
    }
}

Then configure the title suffix:

'fields' => [
    'title' => 'name',
    'title_suffix' => 'metadata.pet_name',  // Shows "Owner (Pet Name)"
],

Using Service Providers

If your bookings are assigned to specific staff members:

'models' => [
    'booking' => \App\Models\Booking::class,
    'service_provider' => \App\Models\User::class,  // Your staff model
],

The widget will automatically add a "Service Provider" select field.

Custom Event Colors

Override the color logic for advanced scenarios:

protected function getEventColors(string $status): array
{
    // Custom logic, e.g., color by service provider
    if ($this->record->service_provider_id === 1) {
        return ['bg' => '#FF6B6B', 'border' => '#EE5555'];
    }

    return parent::getEventColors($status);
}

Migration Guide

From Pet Grooming App

If you're migrating from a pet-specific implementation:

  1. Migrate pet fields to metadata:
DB::table('bookings')->get()->each(function ($booking) {
    DB::table('bookings')
        ->where('id', $booking->id)
        ->update([
            'metadata' => json_encode([
                'pet_name' => $booking->pet_name,
                'breed' => $booking->breed,
                'weight' => $booking->weight,
            ])
        ]);
});
  1. Configure for Bulgarian locale:
'calendar' => [
    'locale' => 'bg',
    'timezone' => 'Europe/Sofia',
],

'statuses' => [
    'непотвърдена' => ['label' => 'Непотвърдена', 'color' => ['bg' => '#EAB308', 'border' => '#CA8A04']],
    'потвърдена' => ['label' => 'Потвърдена', 'color' => ['bg' => '#3B82F6', 'border' => '#2563EB']],
    'успешна' => ['label' => 'Успешна', 'color' => ['bg' => '#10B981', 'border' => '#059669']],
    'отказана' => ['label' => 'Отказана', 'color' => ['bg' => '#EF4444', 'border' => '#DC2626']],
],

API Reference

BookingCalendarWidget Methods

Overridable Methods:

  • getEventTitle($booking): string - Customize event title display
  • getEventColors(string $status): array - Customize event colors
  • getEventExtendedProps($booking): array - Add custom tooltip data
  • formatPhoneNumber(?string $phone): ?string - Custom phone formatting
  • getFormSchema(): array - Customize the booking form

Model Scopes:

Booking::byStatus('confirmed')->get();
Booking::betweenDates('2024-01-01', '2024-01-31')->get();
Booking::upcoming()->get();
Booking::past()->get();

Examples

Salon Booking System

'models' => [
    'booking' => \App\Models\Appointment::class,
    'service_provider' => \App\Models\Stylist::class,
],

'statuses' => [
    'scheduled' => ['label' => 'Scheduled', 'color' => ['bg' => '#3B82F6', 'border' => '#2563EB']],
    'completed' => ['label' => 'Completed', 'color' => ['bg' => '#10B981', 'border' => '#059669']],
    'no_show' => ['label' => 'No Show', 'color' => ['bg' => '#EF4444', 'border' => '#DC2626']],
],

Room Reservations

'models' => [
    'booking' => \App\Models\Reservation::class,
    'resource' => \App\Models\Room::class,
],

'fields' => [
    'title' => 'name',
    'title_suffix' => 'resource.name',  // Shows "Guest (Room 101)"
],

Troubleshooting

Migration Conflicts

If you already have a bookings table, the migration will automatically skip. Configure your own model:

'models' => [
    'booking' => \App\Models\Booking::class,
],

Relationship Errors

If you get "Model not configured" errors, make sure to set the relationship models in config:

'models' => [
    'service_provider' => \App\Models\User::class,  // Required if using this relationship
],

Events Not Showing

  1. Check that your booking model has the required fields
  2. Verify the model is set correctly in config
  3. Check that bookings exist in the database

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

The MIT License (MIT). Please see License File for more information.

Credits

统计信息

  • 总下载量: 1
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 4
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2025-12-19

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固