Files
anyway/frontend/lib/presentation/pages/new_trip_preferences.dart

162 lines
4.6 KiB
Dart

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:anyway/domain/entities/preferences.dart';
import 'package:anyway/presentation/pages/trip_details_page.dart';
import 'package:anyway/presentation/providers/trip_provider.dart';
class NewTripPreferencesPage extends ConsumerStatefulWidget {
const NewTripPreferencesPage({super.key, required this.startLocation});
final List<double> startLocation;
@override
ConsumerState<NewTripPreferencesPage> createState() =>
_NewTripPreferencesPageState();
}
class _NewTripPreferencesPageState
extends ConsumerState<NewTripPreferencesPage> {
int _sightseeing = 3;
int _shopping = 1;
int _nature = 2;
int _maxTimeMinutes = 90;
bool _isCreating = false;
Widget _preferenceSlider(
String name,
int value,
ValueChanged<int> onChanged,
Icon icon,
) {
return Card(
margin: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
child: ListTile(
leading: icon,
title: Text(name),
subtitle: Slider(
value: value.toDouble(),
min: 0,
max: 5,
divisions: 5,
label: value.toString(),
onChanged: (v) => onChanged(v.toInt()),
),
),
);
}
Widget _durationPicker() {
return Card(
margin: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
child: ListTile(
leading: const Icon(Icons.access_time),
title: const Text('Maximum trip duration'),
subtitle: CupertinoTimerPicker(
mode: CupertinoTimerPickerMode.hm,
initialTimerDuration: Duration(minutes: _maxTimeMinutes),
minuteInterval: 15,
onTimerDurationChanged: (Duration newDuration) {
setState(() {
_maxTimeMinutes = newDuration.inMinutes;
});
},
),
),
);
}
Future<void> _onCreatePressed() async {
if (_isCreating) return;
setState(() => _isCreating = true);
final createTrip = ref.read(createTripProvider);
final prefs = Preferences(
scores: {
'sightseeing': _sightseeing,
'shopping': _shopping,
'nature': _nature,
},
maxTimeMinutes: _maxTimeMinutes,
startLocation: widget.startLocation,
);
try {
final trip = await createTrip(prefs);
if (!mounted) return;
ScaffoldMessenger.of(
context,
).showSnackBar(SnackBar(content: Text('Trip created: ${trip.uuid}')));
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(builder: (_) => TripDetailsPage(trip: trip)),
(route) => route.isFirst,
);
} catch (e) {
if (!mounted) return;
ScaffoldMessenger.of(
context,
).showSnackBar(SnackBar(content: Text('Failed to create trip: $e')));
} finally {
if (mounted) setState(() => _isCreating = false);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Trip Preferences')),
body: ListView(
children: [
const Padding(
padding: EdgeInsets.all(16.0),
child: Text(
'Tell us about your ideal trip.',
style: TextStyle(fontSize: 18),
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: Row(
children: [
const Icon(Icons.place),
const SizedBox(width: 8),
Text(
'Start: ${widget.startLocation[0].toStringAsFixed(4)}, ${widget.startLocation[1].toStringAsFixed(4)}',
),
],
),
),
_durationPicker(),
_preferenceSlider(
'Sightseeing',
_sightseeing,
(v) => setState(() => _sightseeing = v),
const Icon(Icons.camera_alt),
),
_preferenceSlider(
'Shopping',
_shopping,
(v) => setState(() => _shopping = v),
const Icon(Icons.shopping_bag),
),
_preferenceSlider(
'Nature',
_nature,
(v) => setState(() => _nature = v),
const Icon(Icons.park),
),
const SizedBox(height: 120), // padding for floating button
],
),
floatingActionButton: FloatingActionButton.extended(
onPressed: _isCreating ? null : _onCreatePressed,
label: _isCreating
? const Text('Creating...')
: const Text('Create Trip'),
icon: const Icon(Icons.playlist_add),
),
);
}
}