| Install | |
|---|---|
composer require karaodin/filament-opening-hours |
|
| Latest Version: | v2.2.1 |
| PHP: | ^8.1|^8.2|^8.3|^8.4 |
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.
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"
use KaraOdin\FilamentOpeningHours\OpeningHoursPlugin;
public function panel(Panel $panel): Panel
{
return $panel
// ...
->plugin(new OpeningHoursPlugin());
}
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);
});
use KaraOdin\FilamentOpeningHours\Components\OpeningHoursForm;
public static function form(Form $form): Form
{
return $form
->schema([
// ... other fields
...OpeningHoursForm::schema(),
]);
}
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(),
]);
}
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(),
]);
}
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
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',
],
];
// 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
// 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
// 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
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
}
}
}
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
composer test
Please see CHANGELOG for more information on what has changed recently.
Please see CONTRIBUTING for details.
Please review our security policy on how to report security vulnerabilities.
The MIT License (MIT). Please see License File for more information.
Experience the difference - try it today! 🚀