smart_seat_selector 0.1.0
smart_seat_selector: ^0.1.0 copied to clipboard
A universal grid-based seat selection widget for Flutter supporting Cinemas, Buses, Flights, and Event halls with zoom and pan interaction.
import 'package:flutter/material.dart';
import 'package:smart_seat_selector/smart_seat_selector.dart';
void main() {
runApp(const MaterialApp(
title: 'Smart Seat Selector Demo',
debugShowCheckedModeBanner: false,
home: SeatSelectorDemo(),
));
}
class SeatSelectorDemo extends StatefulWidget {
const SeatSelectorDemo({super.key});
@override
State<SeatSelectorDemo> createState() => _SeatSelectorDemoState();
}
class _SeatSelectorDemoState extends State<SeatSelectorDemo> {
// Typed grid: VIP front rows, business middle, economy back, wheelchair bays
final TypedSeatGrid _grid = [
// Row A — VIP
[
Seat.vip(),
Seat.vip(),
Seat.vip(),
Seat.gap(),
Seat.gap(),
Seat.vip(),
Seat.vip(),
Seat.vip()
],
// Row B — Business
[
Seat.business(),
Seat.business(booked: true),
Seat.business(),
Seat.gap(),
Seat.gap(),
Seat.business(),
Seat.business(),
Seat.business()
],
// Row C — Business
[
Seat.business(),
Seat.business(),
Seat.business(),
Seat.gap(),
Seat.gap(),
Seat.business(booked: true),
Seat.business(),
Seat.business()
],
// Row D — Economy
[
Seat.economy(),
Seat.economy(),
Seat.economy(),
Seat.gap(),
Seat.gap(),
Seat.economy(),
Seat.economy(),
Seat.economy()
],
// Row E — Economy
[
Seat.economy(booked: true),
Seat.economy(),
Seat.economy(),
Seat.gap(),
Seat.gap(),
Seat.economy(),
Seat.economy(booked: true),
Seat.economy()
],
// Row F — Economy + wheelchair bays at ends
[
Seat.wheelchair(),
Seat.economy(),
Seat.economy(),
Seat.gap(),
Seat.gap(),
Seat.economy(),
Seat.economy(),
Seat.wheelchair()
],
];
late SeatController _controller;
final _config = const SeatLayoutConfig(
seatSize: 40,
showRowLabels: true,
showColLabels: true,
enableAnimations: true,
showTooltip: true,
typeConfigs: {
SeatType.economy: SeatTypeConfig.defaultEconomy,
SeatType.business: SeatTypeConfig.defaultBusiness,
SeatType.vip: SeatTypeConfig.defaultVip,
SeatType.wheelchair: SeatTypeConfig.defaultWheelchair,
},
);
@override
void initState() {
super.initState();
_controller = SeatController(
seatGrid: _grid,
maxSelection: 4,
prices: const {
SeatType.economy: 10.0,
SeatType.business: 25.0,
SeatType.vip: 60.0,
SeatType.wheelchair: 0.0,
},
);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
void _handleConfirm(List<SeatPoint> seats) {
final labels = seats
.map((s) => '${String.fromCharCode(65 + s.row)}${s.col + 1}')
.join(', ');
showDialog(
context: context,
builder: (_) => AlertDialog(
title: const Text('Booking Confirmed'),
content: Text(
'Seats: $labels\nTotal: \$${_controller.totalPriceFormatted}',
),
actions: [
TextButton(
onPressed: () {
Navigator.pop(context);
_controller.clearSelection();
},
child: const Text('Reset'),
),
TextButton(
onPressed: () => Navigator.pop(context),
child: const Text('Done'),
),
],
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey[50],
appBar: AppBar(
title: const Text('Cinema Booking'),
backgroundColor: const Color(0xFF1A237E),
foregroundColor: Colors.white,
actions: [
IconButton(
icon: const Icon(Icons.refresh),
onPressed: _controller.clearSelection,
tooltip: 'Clear selection',
),
],
),
body: Column(
children: [
Expanded(
child: SingleChildScrollView(
child: Column(
children: [
SeatLayout(
controller: _controller,
seatConfig: _config,
headerWidget: Container(
height: 36,
width: 300,
margin: const EdgeInsets.only(bottom: 4),
decoration: BoxDecoration(
color: Colors.grey[300],
borderRadius: const BorderRadius.vertical(
bottom: Radius.circular(80),
),
border: const Border(
top: BorderSide(color: Colors.grey, width: 3),
),
),
alignment: Alignment.center,
child: Text('SCREEN',
style: TextStyle(
letterSpacing: 4,
fontSize: 11,
color: Colors.grey[600],
fontWeight: FontWeight.w600,
)),
),
onSeatStateChanged: (_) => setState(() {}),
),
const SizedBox(height: 8),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: SeatLegend(config: _config, showTypes: true),
),
const SizedBox(height: 16),
],
),
),
),
SeatSummaryBar(
controller: _controller,
config: _config,
confirmLabel: 'Book Tickets',
currencySymbol: '\$',
onConfirm: _handleConfirm,
),
],
),
);
}
}