383 lines
15 KiB
Dart
383 lines
15 KiB
Dart
// lib/screens/booking_screen.dart
|
|
import 'package:flutter/material.dart';
|
|
|
|
class BookingScreen extends StatefulWidget {
|
|
// Keep onBook in the constructor if you want to use it later, but we won't call it here.
|
|
final VoidCallback? onBook;
|
|
final String image;
|
|
|
|
const BookingScreen({
|
|
Key? key,
|
|
this.onBook,
|
|
this.image = 'assets/images/event1.jpg',
|
|
}) : super(key: key);
|
|
|
|
@override
|
|
State<BookingScreen> createState() => _BookingScreenState();
|
|
}
|
|
|
|
class _BookingScreenState extends State<BookingScreen> {
|
|
// small gallery placeholder
|
|
final List<String> gallery = [
|
|
'assets/images/event1.jpg',
|
|
'assets/images/event2.jpg',
|
|
'assets/images/event3.jpeg',
|
|
'assets/images/event1.jpg',
|
|
];
|
|
|
|
// long about text
|
|
final String aboutText = '''
|
|
Some voices don't just sing, they awaken something deep within. Sid Sriram is one of those rare artists who doesn't just perform music... he becomes it.
|
|
|
|
This concert isn't just about a setlist or a stage, it's a journey. A moment suspended in time. A powerful collective experience where every note pulls at memory, every silence says what words never could, and every crescendo feels like it was meant just for you.
|
|
|
|
From the moment the lights go down, you're no longer in the real world — you're in his world: a place shaped by melody and intimacy, where familiar songs are reborn and new ones carve out space in your memory. Expect an award-calibre voice that melts into orchestration, fragile acoustic passages that make the room hold its breath, and thunderous climaxes that lift everyone to their feet.
|
|
|
|
Whether you're a longtime fan or hearing him live for the first time, this evening promises to linger long after the last chord fades — a night of shared emotion, artistry, and music that stays with you.
|
|
''';
|
|
|
|
bool _booked = false;
|
|
|
|
void _performLocalBooking() {
|
|
// mark locally booked (do NOT call widget.onBook())
|
|
if (!_booked) {
|
|
setState(() => _booked = true);
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
SnackBar(content: Text('Tickets booked (demo)')),
|
|
);
|
|
}
|
|
}
|
|
|
|
void _openLearnMoreSheet() {
|
|
showModalBottomSheet(
|
|
context: context,
|
|
isScrollControlled: true,
|
|
backgroundColor: Colors.transparent,
|
|
builder: (ctx) {
|
|
return DraggableScrollableSheet(
|
|
expand: false,
|
|
initialChildSize: 0.78,
|
|
minChildSize: 0.35,
|
|
maxChildSize: 0.95,
|
|
builder: (context, scrollController) {
|
|
return Container(
|
|
decoration: BoxDecoration(
|
|
color: Colors.white,
|
|
borderRadius: BorderRadius.vertical(top: Radius.circular(24.0)),
|
|
boxShadow: [BoxShadow(color: Colors.black26, blurRadius: 8)],
|
|
),
|
|
child: SingleChildScrollView(
|
|
controller: scrollController,
|
|
child: Padding(
|
|
padding: const EdgeInsets.fromLTRB(20, 18, 20, 24),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
// drag handle
|
|
Center(
|
|
child: Container(
|
|
width: 48,
|
|
height: 6,
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey[300],
|
|
borderRadius: BorderRadius.circular(6),
|
|
),
|
|
),
|
|
),
|
|
SizedBox(height: 16),
|
|
|
|
Text(
|
|
"The Homecoming Tour | Sid Sriram Live in Concert",
|
|
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
|
|
),
|
|
SizedBox(height: 12),
|
|
|
|
Row(
|
|
children: [
|
|
Icon(Icons.calendar_today, size: 16, color: Colors.blue),
|
|
SizedBox(width: 8),
|
|
Text("22 Jan - 24 Jan, 2025", style: TextStyle(color: Colors.black54)),
|
|
SizedBox(width: 14),
|
|
Icon(Icons.access_time, size: 16, color: Colors.blue),
|
|
SizedBox(width: 8),
|
|
Text("04:00 PM - 11:00 PM", style: TextStyle(color: Colors.black54)),
|
|
],
|
|
),
|
|
SizedBox(height: 14),
|
|
|
|
Container(
|
|
height: 120,
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey[200],
|
|
borderRadius: BorderRadius.circular(12),
|
|
),
|
|
child: Center(child: Text('Map placeholder — Cultural Hall', style: TextStyle(color: Colors.black45))),
|
|
),
|
|
SizedBox(height: 18),
|
|
|
|
Text('About the Event', style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
|
|
SizedBox(height: 8),
|
|
Text(aboutText, style: TextStyle(color: Colors.black54, height: 1.45)),
|
|
SizedBox(height: 18),
|
|
|
|
Text('Gallery', style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
|
|
SizedBox(height: 12),
|
|
SizedBox(
|
|
height: 78,
|
|
child: ListView.separated(
|
|
scrollDirection: Axis.horizontal,
|
|
itemCount: gallery.length,
|
|
separatorBuilder: (_, __) => SizedBox(width: 12),
|
|
itemBuilder: (context, idx) {
|
|
final path = gallery[idx];
|
|
return ClipRRect(
|
|
borderRadius: BorderRadius.circular(12),
|
|
child: Container(
|
|
width: 78,
|
|
height: 78,
|
|
color: Colors.grey[200],
|
|
child: Image.asset(
|
|
path,
|
|
fit: BoxFit.cover,
|
|
errorBuilder: (ctx, err, st) => Center(child: Icon(Icons.image, color: Colors.grey)),
|
|
),
|
|
),
|
|
);
|
|
},
|
|
),
|
|
),
|
|
|
|
SizedBox(height: 22),
|
|
|
|
// If already booked, show booked UI inside the sheet too (optional)
|
|
if (_booked) ...[
|
|
_bookedRow(),
|
|
SizedBox(height: 12),
|
|
] else ...[
|
|
// Book button inside sheet — now does in-place booking (no navigation)
|
|
SizedBox(
|
|
width: double.infinity,
|
|
child: ElevatedButton(
|
|
style: ElevatedButton.styleFrom(
|
|
padding: EdgeInsets.symmetric(vertical: 16),
|
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
|
|
backgroundColor: Color(0xFF0B63D6),
|
|
foregroundColor: Colors.white,
|
|
),
|
|
onPressed: () {
|
|
// mark booked and close the sheet (no removal from home)
|
|
_performLocalBooking();
|
|
Navigator.of(context).pop();
|
|
},
|
|
child: Text('Book Your Spot', style: TextStyle(fontSize: 16, color: Colors.white)),
|
|
),
|
|
),
|
|
],
|
|
|
|
SizedBox(height: 12),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
},
|
|
);
|
|
},
|
|
);
|
|
}
|
|
|
|
// row shown after booking: left green pill + three action icons on right
|
|
Widget _bookedRow() {
|
|
final Color primary = Color(0xFF0B63D6);
|
|
return Row(
|
|
children: [
|
|
// Tickets Booked pill (left)
|
|
Container(
|
|
padding: EdgeInsets.symmetric(horizontal: 18, vertical: 12),
|
|
decoration: BoxDecoration(
|
|
color: Color(0xFFDFF5DF), // light green background
|
|
borderRadius: BorderRadius.circular(12),
|
|
),
|
|
child: Text('Tickets Booked', style: TextStyle(color: Color(0xFF2E7D32), fontWeight: FontWeight.bold)),
|
|
),
|
|
|
|
Spacer(),
|
|
|
|
// action icons (scanner / chat / call)
|
|
_iconSquare(primary, Icons.qr_code_scanner, onTap: () {
|
|
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('Scanner tapped (demo)')));
|
|
}),
|
|
SizedBox(width: 12),
|
|
_iconSquare(primary, Icons.chat, onTap: () {
|
|
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('Chat tapped (demo)')));
|
|
}),
|
|
SizedBox(width: 12),
|
|
_iconSquare(primary, Icons.call, onTap: () {
|
|
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('Call tapped (demo)')));
|
|
}),
|
|
],
|
|
);
|
|
}
|
|
|
|
Widget _iconSquare(Color bg, IconData icon, {required VoidCallback onTap}) {
|
|
return InkWell(
|
|
onTap: onTap,
|
|
borderRadius: BorderRadius.circular(12),
|
|
child: Container(
|
|
width: 52,
|
|
height: 52,
|
|
decoration: BoxDecoration(
|
|
color: bg,
|
|
borderRadius: BorderRadius.circular(12),
|
|
boxShadow: [BoxShadow(color: Colors.black12, blurRadius: 6, offset: Offset(0, 4))],
|
|
),
|
|
child: Icon(icon, color: Colors.white, size: 24),
|
|
),
|
|
);
|
|
}
|
|
|
|
void _confirmBookingFromMain() {
|
|
// book in-place (no navigation and no removal from home)
|
|
_performLocalBooking();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
// full-bleed image behind status bar
|
|
return Scaffold(
|
|
extendBodyBehindAppBar: true,
|
|
backgroundColor: Colors.black,
|
|
body: Stack(
|
|
children: [
|
|
// full background image
|
|
Positioned.fill(
|
|
child: Image.asset(
|
|
widget.image,
|
|
fit: BoxFit.cover,
|
|
errorBuilder: (ctx, err, st) => Container(color: Colors.grey[900]),
|
|
),
|
|
),
|
|
|
|
// subtle gradient to make bottom white text readable
|
|
Positioned.fill(
|
|
child: Container(
|
|
decoration: BoxDecoration(
|
|
gradient: LinearGradient(
|
|
colors: [Colors.transparent, Colors.black87],
|
|
begin: Alignment.topCenter,
|
|
end: Alignment.bottomCenter,
|
|
stops: [0.45, 1.0],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
|
|
// top safe area controls
|
|
SafeArea(
|
|
child: Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
_smallRoundedButton(icon: Icons.arrow_back, onTap: () => Navigator.pop(context)),
|
|
_smallRoundedButton(icon: Icons.favorite_border, onTap: () {}),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
|
|
// bottom anchored overlay: title, details, either book button or booked row, learn more
|
|
Align(
|
|
alignment: Alignment.bottomCenter,
|
|
child: SafeArea(
|
|
bottom: true,
|
|
child: Padding(
|
|
padding: const EdgeInsets.fromLTRB(20, 12, 20, 16),
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
// Title & details
|
|
Container(
|
|
width: double.infinity,
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
'The Homecoming Tour | Sid Sriram Live in Concert',
|
|
style: TextStyle(color: Colors.white, fontSize: 22, fontWeight: FontWeight.bold),
|
|
),
|
|
SizedBox(height: 10),
|
|
Row(
|
|
children: [
|
|
Icon(Icons.calendar_today, size: 16, color: Colors.white70),
|
|
SizedBox(width: 8),
|
|
Text('22 Jan - 24 Jan', style: TextStyle(color: Colors.white70)),
|
|
SizedBox(width: 12),
|
|
Icon(Icons.location_on, size: 16, color: Colors.white70),
|
|
SizedBox(width: 8),
|
|
Expanded(child: Text('Cultural Hall, Brookefield', style: TextStyle(color: Colors.white70))),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
|
|
SizedBox(height: 16),
|
|
|
|
// If booked: show green pill + icons in-place.
|
|
// Otherwise show the large Book button.
|
|
if (_booked) ...[
|
|
_bookedRow(),
|
|
SizedBox(height: 12),
|
|
] else ...[
|
|
SizedBox(
|
|
width: double.infinity,
|
|
child: ElevatedButton(
|
|
onPressed: _confirmBookingFromMain,
|
|
style: ElevatedButton.styleFrom(
|
|
padding: EdgeInsets.symmetric(vertical: 16),
|
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
|
|
backgroundColor: Color(0xFF0B63D6),
|
|
foregroundColor: Colors.white,
|
|
),
|
|
child: Text('Book Your Spot', style: TextStyle(fontSize: 16, color: Colors.white)),
|
|
),
|
|
),
|
|
SizedBox(height: 12),
|
|
],
|
|
|
|
// Learn more handle (tappable)
|
|
GestureDetector(
|
|
onTap: _openLearnMoreSheet,
|
|
child: Column(
|
|
children: [
|
|
Text('Learn More', style: TextStyle(color: Colors.white70)),
|
|
SizedBox(height: 6),
|
|
Icon(Icons.keyboard_double_arrow_up, color: Colors.white70),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _smallRoundedButton({required IconData icon, required VoidCallback onTap}) {
|
|
return InkWell(
|
|
onTap: onTap,
|
|
borderRadius: BorderRadius.circular(12),
|
|
child: Container(
|
|
width: 44,
|
|
height: 44,
|
|
decoration: BoxDecoration(color: Colors.white24, borderRadius: BorderRadius.circular(12)),
|
|
child: Icon(icon, color: Colors.white),
|
|
),
|
|
);
|
|
}
|
|
}
|