karaodin/filament-opening-hours

A Filament plugin for managing business opening hours with timezone support and exceptions

v2.2.1 2025-07-21 11:05 UTC

This package is auto-updated.

Last update: 2025-07-21 17:01:26 UTC


README

Latest Version on Packagist Total Downloads

A premium-quality Filament plugin for managing business opening hours with advanced timezone support, visual interfaces, and comprehensive exception management. Built on top of spatie/opening-hours.

โœจ Features

  • ๐Ÿ• Advanced Visual Form Builder - Intuitive interface with collapsible sections and live validation
  • ๐ŸŒ Comprehensive Timezone Support - Searchable timezone dropdown with Algeria as default
  • ๐Ÿ“… Smart Exception Management - Modal-based system with date ranges and recurring exceptions
  • ๐ŸŽฏ Multiple Display Modes - Circular charts, status badges, and detailed weekly views
  • ๐Ÿ”„ Global Enable/Disable - Master toggle for entire business hours system
  • ๐Ÿ“Š Rich Table Columns - Interactive circular displays with hover tooltips
  • ๐Ÿ“‹ Enhanced Infolist Entries - Beautiful formatted displays with animations
  • ๐ŸŽจ Premium Styling - Professional gradients, animations, and dark mode support
  • โšก Performance Optimized - Lazy loading assets and efficient queries
  • ๐Ÿ“ฑ Mobile Responsive - Optimized for all screen sizes

๐Ÿš€ Installation

You can install the package via composer:

composer require karaodin/filament-opening-hours

You can publish the config file with:

php artisan vendor:publish --tag="filament-opening-hours-config"

๐Ÿ’ป Usage

1. Add the Plugin to Your Panel

use KaraOdin\FilamentOpeningHours\OpeningHoursPlugin;

public function panel(Panel $panel): Panel
{
    return $panel
        // ...
        ->plugin(new OpeningHoursPlugin());
}

2. Prepare Your Model

Add the trait to your model and ensure you have the required database columns:

use KaraOdin\FilamentOpeningHours\Concerns\HasOpeningHours;

class Restaurant extends Model
{
    use HasOpeningHours;

    protected $casts = [
        'opening_hours' => 'array',
        'opening_hours_exceptions' => 'array',
    ];
}

Migration example:

Schema::table('restaurants', function (Blueprint $table) {
    $table->json('opening_hours')->nullable();
    $table->json('opening_hours_exceptions')->nullable();
    $table->string('timezone')->default('Africa/Algiers');
    $table->boolean('opening_hours_enabled')->default(true);
});

3. Use in Forms

use KaraOdin\FilamentOpeningHours\Components\OpeningHoursForm;

public static function form(Form $form): Form
{
    return $form
        ->schema([
            // ... other fields
            
            ...OpeningHoursForm::schema(),
        ]);
}

4. Display in Tables

use KaraOdin\FilamentOpeningHours\Components\OpeningHoursColumn;

public static function table(Table $table): Table
{
    return $table
        ->columns([
            // ... other columns
            
            // Option 1: Circular visual display (recommended)
            OpeningHoursColumn::make('opening_hours')
                ->label('Hours')
                ->circular()
                ->showTooltips(),
                
            // Option 2: Status badge
            OpeningHoursColumn::make('status')
                ->label('Status')
                ->status(),
                
            // Option 3: Weekly overview
            OpeningHoursColumn::make('schedule')
                ->label('Schedule')
                ->weekly(),
        ]);
}

5. Display in Infolists

use KaraOdin\FilamentOpeningHours\Components\OpeningHoursEntry;

public static function infolist(Infolist $infolist): Infolist
{
    return $infolist
        ->schema([
            // ... other entries
            
            // Option 1: Full details (recommended)
            OpeningHoursEntry::make('opening_hours')
                ->label('Business Hours')
                ->full(),
                
            // Option 2: Status only
            OpeningHoursEntry::make('status')
                ->label('Current Status')
                ->statusOnly(),
                
            // Option 3: Weekly hours only
            OpeningHoursEntry::make('hours')
                ->label('Weekly Schedule')
                ->weeklyHours(),
                
            // Option 4: Compact summary
            OpeningHoursEntry::make('summary')
                ->label('Hours Summary')
                ->compact(),
        ]);
}

๐ŸŽฏ Model Methods

The HasOpeningHours trait provides powerful query methods:

$restaurant = Restaurant::first();

// Check if currently open
$restaurant->isOpen(); // true/false
$restaurant->isClosed(); // true/false

// Check specific times
$restaurant->isOpen(Carbon::parse('2024-01-15 14:30')); // true/false

// Check specific days
$restaurant->isOpenOn('monday'); // true/false
$restaurant->isClosedOn('sunday'); // true/false

// Get next opening/closing times
$restaurant->nextOpen(); // Carbon instance or null
$restaurant->nextClose(); // Carbon instance or null

// Get current status with human readable format
$restaurant->getCurrentStatus(); // "Open until 17:00" or "Closed until 09:00"

// Get hours for specific day/date
$restaurant->getOpeningHoursForDay('monday'); // ['09:00-17:00']
$restaurant->getOpeningHoursForDate(Carbon::today()); // ['09:00-17:00']

// Exception management
$restaurant->addException('2024-12-25', []); // Closed on Christmas
$restaurant->addException('2024-12-31', ['09:00-15:00']); // Special hours
$restaurant->removeException('2024-12-25');
$restaurant->hasException('2024-12-25'); // true/false

โš™๏ธ Configuration

The config file allows you to customize:

return [
    // Default timezone
    'default_timezone' => 'Africa/Algiers',
    
    // Time format for display
    'time_format' => 'H:i',
    
    // Days of the week
    'days' => [
        'monday' => 'Monday',
        'tuesday' => 'Tuesday',
        // ...
    ],
    
    // Default opening hours
    'defaults' => [
        'monday' => ['09:00-17:00'],
        'tuesday' => ['09:00-17:00'],
        // ...
    ],
    
    // Exception types
    'exception_types' => [
        'closed' => 'Closed',
        'holiday' => 'Holiday',
        'special_hours' => 'Special Hours',
        'maintenance' => 'Maintenance',
        'event' => 'Special Event',
    ],
];

๐ŸŽจ Component Options

Form Component

// Complete form schema with all features
...OpeningHoursForm::schema()

// Features included:
// - Global enable/disable toggle
// - Searchable timezone selector
// - Collapsible day sections with duration display
// - Modal-based exception management
// - Recurring annual exceptions
// - Custom labels and descriptions

Table Column Options

// Circular display (default)
OpeningHoursColumn::make('hours')
    ->circular()                    // Circular chart with day segments
    ->showTooltips()               // Hover tooltips with precise times
    ->showCurrentStatus()          // Center status indicator
    ->timezone('Africa/Algiers')   // Custom timezone

// Status badge
OpeningHoursColumn::make('status')
    ->status()                     // Badge with current status
    ->showTooltips()               // Next open/close times in tooltip

// Weekly overview
OpeningHoursColumn::make('weekly')
    ->weekly()                     // 7-day grid view with status dots
    ->showTooltips()               // Day details on hover

Infolist Entry Options

// Full details (default)
OpeningHoursEntry::make('hours')
    ->full()                       // Complete display with all sections
    ->showStatus()                 // Current status section
    ->showExceptions()             // Exceptions and holidays
    ->showTimezone()               // Timezone information

// Status only
OpeningHoursEntry::make('status')
    ->statusOnly()                 // Just current status with animation

// Weekly hours
OpeningHoursEntry::make('schedule')
    ->weeklyHours()                // Weekly schedule grid

// Compact summary
OpeningHoursEntry::make('summary')
    ->compact()                    // Minimal overview with stats

๐Ÿ“Š Data Structure

The plugin stores data in this enhanced format:

{
    "opening_hours_enabled": true,
    "timezone": "Africa/Algiers",
    "opening_hours": {
        "monday": {
            "enabled": true,
            "hours": [
                {"from": "09:00", "to": "12:00"},
                {"from": "14:00", "to": "17:00"}
            ]
        },
        "tuesday": {
            "enabled": true,
            "hours": [{"from": "09:00", "to": "17:00"}]
        },
        "wednesday": {"enabled": false},
        // ... other days
    },
    "opening_hours_exceptions": {
        "2024-12-25": {
            "type": "holiday",
            "label": "Christmas Day",
            "note": "Merry Christmas!",
            "hours": [],
            "recurring": false
        },
        "12-31": {
            "type": "special_hours",
            "label": "New Year's Eve",
            "hours": [{"from": "09:00", "to": "15:00"}],
            "recurring": true
        }
    }
}

๐ŸŽฏ Advanced Features

Exception Management

  • Modal Interface: Clean, intuitive exception management
  • Date Ranges: Vacation periods, seasonal closures (e.g., July 1-15)
  • Recurring Exceptions: Annual holidays (e.g., every December 25th)
  • Single Dates: Specific holidays or one-time closures
  • Custom Labels: Personalized exception names
  • Multiple Types: Holiday, Closed, Special Hours, Maintenance, Events
  • Rich Descriptions: Additional notes for each exception

Visual Enhancements

  • Circular Charts: SVG-based day segments with hover effects
  • Status Animations: Pulsing indicators and progress bars
  • Gradient Styling: Professional color schemes
  • Dark Mode: Full dark theme support
  • Mobile Responsive: Optimized for all devices

Performance Features

  • Lazy Loading: Assets loaded only when needed
  • Efficient Queries: Optimized database interactions
  • Caching Support: Built-in cache compatibility
  • Error Handling: Graceful degradation on errors

๐Ÿ”ง Multi-Tenancy Support

Compatible with stancl/tenancy:

// In TenantPanelProvider (not OwnerPanelProvider)
->plugins([
    \KaraOdin\FilamentOpeningHours\OpeningHoursPlugin::make(),
])

// Tenant-specific migration
php artisan make:migration add_opening_hours_to_businesses --path=database/migrations/tenant

// Run across all tenants
php artisan tenants:migrate --path=database/migrations/tenant

๐Ÿ“ฑ Browser Support

  • โœ… Chrome 80+
  • โœ… Firefox 75+
  • โœ… Safari 13+
  • โœ… Edge 80+
  • โœ… Mobile Safari
  • โœ… Chrome Mobile

๐Ÿš€ Requirements

  • PHP 8.1+
  • Laravel 10.0+
  • Filament 3.0+

๐Ÿงช Testing

composer test

๐Ÿ“ Changelog

Please see CHANGELOG for more information on what has changed recently.

๐Ÿค Contributing

Please see CONTRIBUTING for details.

๐Ÿ”’ Security Vulnerabilities

Please review our security policy on how to report security vulnerabilities.

๐Ÿ™ Credits

๐Ÿ“„ License

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

๐ŸŒŸ Why Choose This Plugin?

vs. Paid Alternatives

  • โœ… Free & Open Source
  • โœ… More Features than most paid plugins
  • โœ… Better Performance with lazy loading
  • โœ… Modern UI/UX with animations and gradients
  • โœ… Active Development with regular updates

Premium Features

  • ๐ŸŽจ Professional Design - Matches Filament's aesthetic perfectly
  • โšก Performance Optimized - Minimal impact on load times
  • ๐Ÿ”ง Highly Customizable - Multiple display modes and options
  • ๐Ÿ“ฑ Mobile First - Responsive design for all devices
  • ๐ŸŒ™ Dark Mode Ready - Full dark theme support
  • โ™ฟ Accessibility - WCAG compliant with proper ARIA labels

Experience the difference - try it today! ๐Ÿš€