Files
Eventify-frontend/lib/screens/booking_screen.dart

383 lines
15 KiB
Dart
Raw Permalink Normal View History

2026-01-31 15:23:18 +05:30
// 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),
),
);
}
}