UAS/lib/widgets/schedule_selection_widget.dart
2025-12-13 11:36:09 +07:00

305 lines
11 KiB
Dart

import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import '../models/film.dart';
import '../data/app_data.dart';
import '../pages/login_page.dart';
import '../pages/seat_selection_page.dart';
class ScheduleSelectionWidget extends StatefulWidget {
final Film film;
final String username;
final bool isGuest;
const ScheduleSelectionWidget({
super.key,
required this.film,
required this.username,
required this.isGuest,
});
@override
State<ScheduleSelectionWidget> createState() =>
_ScheduleSelectionWidgetState();
}
class _ScheduleSelectionWidgetState extends State<ScheduleSelectionWidget> {
String? _selectedDate;
String _selectedCinema = AppData.cinemas[0];
@override
void initState() {
super.initState();
if (widget.film.schedules[_selectedCinema] != null) {
_selectedDate = widget.film.schedules[_selectedCinema]!.keys.first;
}
}
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.all(24),
decoration: BoxDecoration(
color: const Color(0xFF1F2937),
borderRadius: BorderRadius.circular(12),
border: Border.all(color: const Color(0xFF374151)),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Row(
children: [
Icon(Icons.calendar_today, color: Color(0xFFFBBF24)),
SizedBox(width: 8),
Text(
'Pilih Bioskop, Tanggal & Jadwal',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
],
),
const SizedBox(height: 16),
// Cinema Selection
const Text(
'Bioskop',
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14),
),
const SizedBox(height: 8),
Wrap(
spacing: 8,
runSpacing: 8,
children: AppData.cinemas.map((cinema) {
final isSelected = _selectedCinema == cinema;
return InkWell(
onTap: () {
setState(() {
_selectedCinema = cinema;
if (widget.film.schedules[cinema] != null) {
_selectedDate = widget.film.schedules[cinema]!.keys.first;
}
});
},
child: Container(
padding:
const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
decoration: BoxDecoration(
color: isSelected
? const Color(0xFFFBBF24)
: const Color(0xFF374151),
borderRadius: BorderRadius.circular(8),
border: Border.all(
color: isSelected
? const Color(0xFFFBBF24)
: Colors.transparent,
width: 2,
),
),
child: Text(
cinema,
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w600,
color: isSelected ? Colors.black : Colors.white,
),
),
),
);
}).toList(),
),
const SizedBox(height: 24),
// Date Selection
const Text(
'Tanggal',
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14),
),
const SizedBox(height: 8),
SizedBox(
height: 80,
child: widget.film.schedules[_selectedCinema] != null
? ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: widget.film.schedules[_selectedCinema]!.length,
itemBuilder: (context, index) {
final dateStr = widget
.film.schedules[_selectedCinema]!.keys
.elementAt(index);
final date = DateTime.parse(dateStr);
final isSelected = _selectedDate == dateStr;
return Padding(
padding: const EdgeInsets.only(right: 12),
child: InkWell(
onTap: () => setState(() => _selectedDate = dateStr),
child: Container(
width: 80,
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: isSelected
? const Color(0xFFFBBF24)
: const Color(0xFF374151),
borderRadius: BorderRadius.circular(12),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
DateFormat('EEE').format(date),
style: TextStyle(
fontSize: 12,
color:
isSelected ? Colors.black : Colors.grey,
),
),
const SizedBox(height: 4),
Text(
DateFormat('dd').format(date),
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: isSelected
? Colors.black
: Colors.white,
),
),
Text(
DateFormat('MMM').format(date),
style: TextStyle(
fontSize: 12,
color:
isSelected ? Colors.black : Colors.grey,
),
),
],
),
),
),
);
},
)
: const Center(child: Text('Tidak ada jadwal tersedia')),
),
const SizedBox(height: 24),
if (widget.isGuest)
Center(
child: Column(
children: [
const SizedBox(height: 24),
const Text(
'Anda harus login untuk memesan tiket',
style: TextStyle(color: Colors.grey),
),
const SizedBox(height: 16),
ElevatedButton(
onPressed: () {
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (_) => const LoginPage()),
(route) => false,
);
},
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFFFBBF24),
foregroundColor: Colors.black,
),
child: const Text('Login Sekarang'),
),
const SizedBox(height: 24),
],
),
)
else if (widget.film.schedules[_selectedCinema] != null &&
_selectedDate != null) ...[
const Divider(color: Color(0xFF374151)),
const SizedBox(height: 16),
const Text(
'Jam Tayang',
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16),
),
const SizedBox(height: 12),
Wrap(
spacing: 12,
runSpacing: 12,
children: widget
.film.schedules[_selectedCinema]![_selectedDate]!.keys
.map((time) {
final seats = widget
.film.schedules[_selectedCinema]![_selectedDate]![time]!;
final availableSeats = seats
.expand((row) => row)
.where((s) => s == 'available')
.length;
return ElevatedButton(
onPressed: availableSeats > 0
? () {
Navigator.push(
context,
MaterialPageRoute(
builder: (_) => SeatSelectionPage(
film: widget.film,
date: _selectedDate!,
schedule: time,
username: widget.username,
cinema: _selectedCinema,
),
),
);
}
: null,
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFF374151),
padding: const EdgeInsets.symmetric(
horizontal: 24, vertical: 16),
minimumSize: const Size(120, 60),
),
child: Column(
children: [
Text(
time,
style: const TextStyle(
fontWeight: FontWeight.bold, fontSize: 16),
),
const SizedBox(height: 4),
Text(
availableSeats > 0 ? '$availableSeats kursi' : 'Penuh',
style: TextStyle(
fontSize: 11,
color: availableSeats > 0
? const Color(0xFFFBBF24)
: Colors.red,
),
),
],
),
);
}).toList(),
),
const SizedBox(height: 24),
const Divider(color: Color(0xFF374151)),
const SizedBox(height: 16),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text('Harga Tiket', style: TextStyle(color: Colors.grey)),
Text(
'Rp ${_formatPrice(widget.film.price)}',
style: const TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: Color(0xFFFBBF24),
),
),
],
),
],
],
),
);
}
String _formatPrice(int price) {
return price.toString().replaceAllMapped(
RegExp(r'(\d{1,3})(?=(\d{3})+(?!\d))'),
(m) => '${m[1]}.',
);
}
}