przwl / cine-reserve
A seamless, user-friendly Filament plugin for adding interactive movie seat selection and booking functionality to any Laravel application.
Installs: 10
Dependents: 0
Suggesters: 0
Security: 0
Stars: 1
Watchers: 0
Forks: 0
Open Issues: 0
Language:Blade
pkg:composer/przwl/cine-reserve
README
A seamless, user-friendly plugin for adding interactive movie seat selection and booking functionality to any Laravel application.
🎬 Features
- Interactive Seat Selection: Beautiful, Customizable animated seat selection interface
- Movie Information Display: Showcase movie details.
- Customizable Colors: Choose seat colors for booked, available and selected seats.
- Dynamic Layout: Configure rows and seats per row via config
- Maximum Selection Limit: Set limits on seat selection per session
- Pricing Display: Built-in pricing UI with price per seat and total calculation
- Dark Mode Support: Fully supports Filament's dark mode
- Extensible: Easy to extend and customize
📦 Installation
Install via Composer
composer require przwl/cine-reserve
Register Plugin
In AdminPanelProvider.php:
Register the plugin from ->plugins([])
use Przwl\CineReserve\Filament\CineReserve; public function panel(Panel $panel): Panel { return $panel ->plugins([ CineReserve::make(), ]); }
Publish Config
php artisan vendor:publish --tag=cine-reserve-config
⚙️ Quick Configuration
Edit config/cine-reserve.php:
// Navigation 'register_navigation' => false, // Show/hide navigation item // Movie Information 'show_movie_information' => true, // Show/hide movie information component 'movie_information_fields' => [ 'poster' => true, 'title' => true, 'genre' => true, 'duration' => true, 'rating' => true, 'date' => true, 'start_time' => true, 'end_time' => true, 'theater' => true, ], // Screen & Layout 'show_screen' => true, // Show/hide screen indicator 'select_seats_title_position' => 'left', // 'left', 'center', or 'right' // Seat layout 'rows' => ['A', 'B', 'C', 'D', 'E'], 'seats_per_row' => 8, // Maximum seats per selection (null = unlimited) 'max_selection_limit' => null, // Seat colors 'seat_colors' => [ 'available' => 'green', 'selected' => 'red', 'booked' => 'gray', ], // Pricing configuration 'price_per_seat' => 10.00, // Price per seat (all seats same price) 'show_price_per_seat' => true, // Display price per seat in UI 'currency_symbol' => '$', // Currency symbol for price display
🚀 Quick Start
1. Create Custom SelectSeats Page
php artisan make:filament-page CustomSelectSeats --type=custom
2. Extend SelectSeats Class
namespace App\Filament\Pages; use Przwl\CineReserve\Filament\Pages\SelectSeats; use App\Models\Movie; use App\Models\Showtime; use App\Models\Booking; use Illuminate\Support\Facades\Storage; class CustomSelectSeats extends SelectSeats { public ?int $showtimeId = null; public $total = 0; public function mount(?int $showtimeId = null): void { parent::mount(); if ($showtimeId) { $this->showtimeId = $showtimeId; $this->loadShowtimeData($showtimeId); } } protected function loadShowtimeData(int $showtimeId): void { $showtime = Showtime::with('movie')->findOrFail($showtimeId); $movie = $showtime->movie; // Set movie information $this->movieTitle = $movie->title; $this->moviePosterUrl = $movie->poster_url ? Storage::disk('public')->url($movie->poster_url) : null; $this->movieGenre = $movie->genre; $this->movieDuration = $movie->duration . ' min'; $this->movieRating = $movie->rating; $this->movieDate = $showtime->date->format('F j, Y'); $this->movieStartTime = \Carbon\Carbon::parse($showtime->start_time)->format('g:i A'); $this->movieEndTime = \Carbon\Carbon::parse($showtime->end_time)->format('g:i A'); $this->movieTheater = $showtime->theater_name; // Load booked seats $this->bookedSeats = Booking::where('showtime_id', $showtimeId) ->where('status', '!=', 'cancelled') ->get() ->pluck('seat_ids') ->flatten() ->unique() ->values() ->toArray(); } public function proceed(): void { if (empty($this->selectedSeats)) { Notification::make() ->title('Please select at least one seat') ->warning() ->send(); return; } $this->calculateTotal(); parent::proceed(); } protected function handleBooking(array $selectedSeatDetails): void { // Create booking $booking = Booking::create([ 'showtime_id' => $this->showtimeId, 'user_id' => Auth::id(), 'seat_ids' => $this->selectedSeats, 'total_amount' => $this->total, 'status' => 'pending', ]); $this->selectedSeats = []; $this->total = 0; Notification::make() ->title('Seats booked successfully') ->success() ->send(); } }
📖 Complete Integration Guide
For detailed integration instructions, database migrations, models, and advanced customization, see the Integration Guide.
💰 Pricing Feature
CineReserve includes a built-in pricing display system that shows:
- Total Price: Automatically calculated based on selected seats
- Price Per Seat: Configurable via config
- Selected Seat Details: Displays all selected seat labels (e.g., A1, A2, B3)
- Currency Formatting: Customizable currency symbol
Pricing Configuration
Configure pricing in config/cine-reserve.php:
'price_per_seat' => 10.00, // Default price per seat 'show_price_per_seat' => true, // Show/hide price per seat in UI 'currency_symbol' => '$', // Currency symbol ($, €, ₹, £, etc.)
The pricing is automatically calculated based on the number of selected seats multiplied by the price per seat configured in the config file.
🎨 Customization
Override Methods
The SelectSeats class is designed to be easily extensible:
mount()- Load data and initialize booked seatstoggleSeat()- Add validation (e.g., prevent booking already booked seats)proceed()- Add validation before bookinghandleBooking()- Implement booking logic (save to database, notifications, etc.)
Customize Views
To customize the appearance and layout of the seat selection interface, you can publish the views:
php artisan vendor:publish --tag=cine-reserve-views
This will copy all view files to resources/views/vendor/cine-reserve/ where you can modify them:
select-seats.blade.php- Main seat selection page layoutcomponents/movie-information.blade.php- Movie information display componentpricing-display.blade.php- Pricing information displayproceed-button.blade.php- Proceed to booking buttonscreen.blade.php- Screen indicator component
After publishing, edit these files in resources/views/vendor/cine-reserve/ to match your design requirements. The package will automatically use your customized views instead of the default ones.
Publish Translations
php artisan vendor:publish --tag=cine-reserve-translations
🎯 Events
seatSelected
Emitted when user clicks "Proceed to Booking":
[
'selectedSeats' => [1, 2, 3], // Array of seat IDs
'seatDetails' => [ // Full seat information
['id' => 1, 'row' => 'A', 'number' => '1', 'label' => 'A1'],
],
'count' => 3, // Number of selected seats
'total' => 30.00 // Total price (calculated)
]
📝 Available Movie Properties
Set these properties in your SelectSeats component:
$moviePosterUrl- URL or path to movie poster$movieTitle- Movie title$movieGenre- Movie genre (string, array of strings, or array of enum objects)$movieDuration- Movie duration$movieRating- Movie rating$movieDate- Show date$movieStartTime- Show start time$movieEndTime- Show end time$movieTheater- Theater name$moviePosterAlt- Alt text for poster
Sample Values
When no movie information is provided, the component automatically displays sample/demo values so you can see how it looks:
- Title: "Sample Movie Title"
- Genre: "Action"
- Duration: "120 min"
- Rating: "PG-13"
- Date: Current date (formatted)
- Start Time: "7:00 PM"
- End Time: "9:30 PM"
- Theater: "Theater 1"
This helps you visualize the component structure before implementing your own data. Once you set the movie properties, the actual data will replace the sample values.
⚠️ Important: File Storage Configuration
Movie poster images must be stored on the public disk for proper display.
Configuring Filament FileUpload
When using Filament's FileUpload component for movie posters, ensure you configure it to use the public disk:
use Filament\Forms\Components\FileUpload; FileUpload::make('poster_url') ->image() ->disk('public') // Required: Use public disk ->visibility('public') // Required: Set visibility to public ->required(),
Why is this required? The movie information component displays images directly in the browser. Files stored on private disks cannot be accessed via direct URLs and will not display correctly. Using the public disk ensures that poster images are accessible and display properly.
🎨 Color Options
Available seat colors: amber, gray, red, green, purple, yellow
📄 License
MIT License - see LICENSE file for details
👤 Author
prazwal-bns
- Email: prajwalbns15@gmail.com
- GitHub: @prazwal-bns
Built with ❤️ By Prajwal