otapp_bus_seat_map 0.1.0
otapp_bus_seat_map: ^0.1.0 copied to clipboard
A flexible bus seat map widget for Flutter. Designed for bus booking apps using Otapp Services API.
Otapp Bus Seat Map #
A flexible bus seat map widget for Flutter. Designed for bus booking apps using Otapp Services API or manual configuration.
Features #
- Works directly with Otapp Services API response format
- Manual setup option for custom implementations
- Automatic aisle detection
- Support for special elements (doors, toilets, stairs)
- Customizable seat appearance
- VIP/category support
- Seat status management (available, booked, selected, processing)
- InteractiveViewer support for zoom/pan
Installation #
dependencies:
otapp_bus_seat_map:
git:
url: https://github.com/benardmseti/otapp_bus_seat_map.git
Option 1: Using Otapp Services API #
If you're using the Otapp Services API, the seat map response works directly with this package.
API Response Format #
The Otapp API returns seat data in this format:
{
"lower_seat_map": [
{"seat_row1": "L-1-1-1,L-1-1-2,0,L-1-1-3,L-1-1-4"},
{"seat_row2": "L-1-2-5,L-1-2-6,0,L-1-2-7,L-1-2-8"},
{"seat_row3": "@,0,0,L-1-3-9,L-1-3-10"},
{"seat_row4": "*,0,0,L-1-4-11,L-1-4-12"}
],
"available_seats": "L-1-1-1,L-1-1-2,L-1-1-3,L-1-2-5,L-1-2-7",
"process_seats": "L-1-2-8",
"is_right_hand_drive": 1,
"seat_types": [
{"seat_type_name": "VIP", "seats": "L-1-1-1,L-1-1-2", "fare": [{"fare": "35000"}]},
{"seat_type_name": "Standard", "seats": "L-1-1-3,L-1-1-4", "fare": [{"fare": "25000"}]}
]
}
Using with Otapp API #
import 'package:otapp_bus_seat_map/otapp_bus_seat_map.dart';
// Parse directly from API response
final layout = SeatLayout.fromJson(
apiResponse['lower_seat_map'],
config: SeatLayoutConfig.bus(),
);
// Apply seat statuses from API
final layoutWithStatus = SeatLayout.fromCsvRowsWithStatus(
layout.rawRows,
config: SeatLayoutConfig.bus(),
availableSeats: apiResponse['available_seats'],
bookedSeats: apiResponse['booked_seats'] ?? '',
processingSeats: apiResponse['process_seats'] ?? '',
);
// Use the widget
SeatMapWidget(
layout: layoutWithStatus,
selectedSeats: selectedSeats,
onSeatTap: (seat) {
// Handle seat selection
},
)
Option 2: Manual Setup #
You can also define seat layouts manually without an API.
CSV Format #
Each row is a comma-separated string. Use markers for special elements:
| Code | Element | Description |
|---|---|---|
0 |
Empty/Aisle | Empty space or walkway |
@ |
Door | Entry/exit door |
* |
Toilet | WC/restroom |
# |
Stairs | For double-decker buses |
| Any other | Seat | Regular bookable seat |
Manual Layout Example #
import 'package:otapp_bus_seat_map/otapp_bus_seat_map.dart';
// Define your seat layout manually
final rows = [
'1A,1B,0,1C,1D', // Row 1: 2 seats, aisle, 2 seats
'2A,2B,0,2C,2D', // Row 2: same pattern
'@,0,0,3C,3D', // Row 3: door on left, 2 seats on right
'4A,4B,0,4C,4D', // Row 4: normal row
'*,0,0,5C,5D', // Row 5: toilet on left, 2 seats on right
'6A,6B,6C,6D,6E', // Back row: 5 seats, no aisle
];
// Parse the layout
final layout = SeatLayout.fromCsvRows(
rows,
config: SeatLayoutConfig.bus(defaultPrice: 25000),
);
// Use the widget
SeatMapWidget(
layout: layout,
selectedSeats: selectedSeats,
onSeatTap: (seat) => handleSelection(seat),
)
With Custom Pricing & Categories #
final vipSeats = {'1A', '1B', '1C', '1D'};
final layout = SeatLayout.fromCsvRows(
rows,
config: SeatLayoutConfig.bus(
defaultPrice: 25000,
categoryResolver: (code, metadata) {
if (vipSeats.contains(code)) return 'VIP';
return 'Standard';
},
priceResolver: (code, category, metadata) {
if (category == 'VIP') return 35000;
return 25000;
},
),
);
Customization #
Custom Seat Widget #
SeatMapWidget(
layout: layout,
seatBuilder: (context, seat, isSelected) {
return Container(
width: 50,
height: 50,
decoration: BoxDecoration(
color: isSelected ? Colors.blue : Colors.white,
borderRadius: BorderRadius.circular(8),
),
child: Center(child: Text(seat.label ?? '')),
);
},
)
Custom Special Elements #
SeatMapWidget(
layout: layout,
specialBuilder: (context, element) {
if (element.type == SeatElementType.door) {
return MyCustomDoorWidget();
}
return DefaultSpecialWidget(element: element);
},
)
With Selection Controller #
SeatMapController(
layout: layout,
maxSelection: 4,
onSelectionChanged: (seats) {
print('Selected: ${seats.map((s) => s.label).join(", ")}');
print('Total: ${seats.fold(0.0, (sum, s) => sum + s.price)}');
},
builder: (context, layout, selectedSeats, onSeatTap) {
return SeatMapWidget(
layout: layout,
selectedSeats: selectedSeats,
onSeatTap: onSeatTap,
);
},
)
Configuration Options #
SeatLayoutConfig #
| Property | Default | Description |
|---|---|---|
emptyMarkers |
{'0', ''} |
Codes that represent empty spaces |
doorMarker |
'@' |
Code for door elements |
toiletMarker |
'*' |
Code for toilet elements |
stairsMarker |
'#' |
Code for stairs |
autoDetectAisle |
true |
Auto-detect aisle columns |
delimiter |
',' |
Separator for row strings |
SeatMapWidget #
| Property | Default | Description |
|---|---|---|
seatSize |
50 |
Width/height of each seat |
seatSpacing |
4 |
Horizontal spacing between seats |
rowSpacing |
4 |
Vertical spacing between rows |
showRowLabels |
false |
Show row numbers on left |
enableZoom |
false |
Enable InteractiveViewer |
minScale |
0.5 |
Minimum zoom scale |
maxScale |
3.0 |
Maximum zoom scale |
About Otapp Services #
This package is designed to work seamlessly with the Otapp Services bus booking API. For API access and documentation, contact Otapp Services.
License #
MIT License