Skip to content

Commit

Permalink
perf(booking_form): set Cabin reference on CabinDropdown changed (#…
Browse files Browse the repository at this point in the history
…184)

* perf(booking_form): set `Cabin` reference on `CabinDropdown` changed

* perf(cabin_dropdown): use `Cabin` object as dropdown value
  • Loading branch information
albertms10 committed Jan 15, 2023
1 parent e514629 commit 3b5b404
Show file tree
Hide file tree
Showing 2 changed files with 148 additions and 168 deletions.
304 changes: 142 additions & 162 deletions lib/widgets/booking/booking_form.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:intl/intl.dart';
import 'package:provider/provider.dart';

class BookingForm extends StatefulWidget {
final Booking booking;
Expand Down Expand Up @@ -61,6 +60,7 @@ class _BookingFormState extends State<BookingForm> {
_recurringEndDate = booking.recurringEndDate;

_endDateController.text = DateFormat.yMd().format(_recurringEndDate!);
_occurrencesController.text = '${booking.occurrences}';
}
}

Expand All @@ -81,20 +81,15 @@ class _BookingFormState extends State<BookingForm> {
_startTimeController.text = _startTime!.format(context);
_endTimeController.text = _endTime!.format(context);

final booking = _booking;
if (booking is RecurringBooking) {
_occurrencesController.text = '${booking.occurrences}';
}

return Form(
key: _formKey,
child: Column(
children: [
CabinDropdown(
value: _booking.cabin!.id,
onChanged: (value) {
if (value == null) return;
setState(() => _booking.cabin?.id = value);
cabin: _booking.cabin!,
onChanged: (cabin) {
if (cabin == null) return;
setState(() => _booking.cabin = cabin);
},
),
const SizedBox(height: 24),
Expand Down Expand Up @@ -126,167 +121,152 @@ class _BookingFormState extends State<BookingForm> {
children: [
Expanded(
flex: 10,
child: Consumer<CabinCollection>(
builder: (context, cabinCollection, child) {
return TextFormField(
controller: _startTimeController,
decoration: InputDecoration(
icon: const Icon(Icons.schedule),
labelText: appLocalizations.start,
),
onTap: () async {
final time = await showTimePicker(
context: context,
initialTime: _startTime!,
initialEntryMode: Platform.isMacOS ||
Platform.isWindows ||
Platform.isLinux
? TimePickerEntryMode.input
: TimePickerEntryMode.dial,
);

if (time == null) return;

setState(() {
_startTime = time;
_startTimeController.text = time.format(context);
});
},
onSaved: (value) {
final timeOfDay =
TimeOfDayExtension.tryParse(value ?? '');
if (timeOfDay == null) return;
_booking.startDate =
_booking.startDate!.addLocalTimeOfDay(timeOfDay);
},
validator: (value) {
if (value == null || value.isEmpty) {
return appLocalizations.enterStartTime;
}

final parsedTimeOfDay =
TimeOfDayExtension.tryParse(value);

if (parsedTimeOfDay == null) {
return appLocalizations.enterStartTime;
}

_booking.startDate = _booking.startDate!
.addLocalTimeOfDay(parsedTimeOfDay);

if (_startTime != parsedTimeOfDay) {
_startTime = parsedTimeOfDay;
}

final parsedDateTime = widget.booking.dateOnly!
.addLocalTimeOfDay(parsedTimeOfDay);

if (parsedDateTime.isAfter(
widget.booking.dateOnly!.addLocalTimeOfDay(
_endTime ?? TimeOfDay.now(),
),
) ||
parsedDateTime.isBefore(
widget.booking.dateOnly!
.addLocalTimeOfDay(kTimeTableStartTime),
)) {
return appLocalizations.enterValidRange;
}

if (cabinCollection
.cabinFromId(_booking.cabin?.id)
.bookingCollection
.bookingsOverlapWith(_booking)) {
return appLocalizations.occupied;
}

return null;
},
autovalidateMode: AutovalidateMode.always,
child: TextFormField(
controller: _startTimeController,
decoration: InputDecoration(
icon: const Icon(Icons.schedule),
labelText: appLocalizations.start,
),
onTap: () async {
final time = await showTimePicker(
context: context,
initialTime: _startTime!,
initialEntryMode: Platform.isMacOS ||
Platform.isWindows ||
Platform.isLinux
? TimePickerEntryMode.input
: TimePickerEntryMode.dial,
);

if (time == null) return;

setState(() {
_startTime = time;
_startTimeController.text = time.format(context);
});
},
onSaved: (value) {
final timeOfDay = TimeOfDayExtension.tryParse(value ?? '');
if (timeOfDay == null) return;
_booking.startDate =
_booking.startDate!.addLocalTimeOfDay(timeOfDay);
},
validator: (value) {
if (value == null || value.isEmpty) {
return appLocalizations.enterStartTime;
}

final parsedTimeOfDay = TimeOfDayExtension.tryParse(value);

if (parsedTimeOfDay == null) {
return appLocalizations.enterStartTime;
}

_booking.startDate =
_booking.startDate!.addLocalTimeOfDay(parsedTimeOfDay);

if (_startTime != parsedTimeOfDay) {
_startTime = parsedTimeOfDay;
}

final parsedDateTime = widget.booking.dateOnly!
.addLocalTimeOfDay(parsedTimeOfDay);

if (parsedDateTime.isAfter(
widget.booking.dateOnly!.addLocalTimeOfDay(
_endTime ?? TimeOfDay.now(),
),
) ||
parsedDateTime.isBefore(
widget.booking.dateOnly!
.addLocalTimeOfDay(kTimeTableStartTime),
)) {
return appLocalizations.enterValidRange;
}

if (_booking.cabin?.bookingCollection
.bookingsOverlapWith(_booking) ??
false) {
return appLocalizations.occupied;
}

return null;
},
autovalidateMode: AutovalidateMode.always,
),
),
const SizedBox(width: 16),
Expanded(
flex: 8,
child: Consumer<CabinCollection>(
builder: (context, cabinCollection, child) {
return TextFormField(
controller: _endTimeController,
decoration:
InputDecoration(labelText: appLocalizations.end),
onTap: () async {
final time = await showTimePicker(
context: context,
initialTime: _endTime!,
initialEntryMode: Platform.isMacOS ||
Platform.isWindows ||
Platform.isLinux
? TimePickerEntryMode.input
: TimePickerEntryMode.dial,
);

if (time == null) return;

setState(() {
_endTime = time;
_endTimeController.text = time.format(context);
});
},
onSaved: (value) {
final timeOfDay =
TimeOfDayExtension.tryParse(value ?? '');
if (timeOfDay == null) return;
_booking.endDate =
_booking.endDate!.addLocalTimeOfDay(timeOfDay);
},
validator: (value) {
if (value == null || value.isEmpty) {
return appLocalizations.enterEndTime;
}

final parsedTimeOfDay =
TimeOfDayExtension.tryParse(value);

if (parsedTimeOfDay == null) {
return appLocalizations.enterEndTime;
}

_booking.endDate = _booking.endDate!
.addLocalTimeOfDay(parsedTimeOfDay);

if (_endTime != parsedTimeOfDay) {
_endTime = parsedTimeOfDay;
}

final parsedDateTime = widget.booking.dateOnly!
.addLocalTimeOfDay(parsedTimeOfDay);

if (parsedDateTime.isBefore(
widget.booking.dateOnly!.addLocalTimeOfDay(
_startTime ?? TimeOfDay.now(),
),
) ||
parsedDateTime.isAfter(
widget.booking.dateOnly!
.addLocalTimeOfDay(kTimeTableEndTime),
)) {
return appLocalizations.enterValidRange;
}

if (cabinCollection
.cabinFromId(_booking.cabin?.id)
.bookingCollection
.bookingsOverlapWith(_booking)) {
return appLocalizations.occupied;
}

return null;
},
autovalidateMode: AutovalidateMode.always,
child: TextFormField(
controller: _endTimeController,
decoration: InputDecoration(labelText: appLocalizations.end),
onTap: () async {
final time = await showTimePicker(
context: context,
initialTime: _endTime!,
initialEntryMode: Platform.isMacOS ||
Platform.isWindows ||
Platform.isLinux
? TimePickerEntryMode.input
: TimePickerEntryMode.dial,
);

if (time == null) return;

setState(() {
_endTime = time;
_endTimeController.text = time.format(context);
});
},
onSaved: (value) {
final timeOfDay = TimeOfDayExtension.tryParse(value ?? '');
if (timeOfDay == null) return;
_booking.endDate =
_booking.endDate!.addLocalTimeOfDay(timeOfDay);
},
validator: (value) {
if (value == null || value.isEmpty) {
return appLocalizations.enterEndTime;
}

final parsedTimeOfDay = TimeOfDayExtension.tryParse(value);

if (parsedTimeOfDay == null) {
return appLocalizations.enterEndTime;
}

_booking.endDate =
_booking.endDate!.addLocalTimeOfDay(parsedTimeOfDay);

if (_endTime != parsedTimeOfDay) {
_endTime = parsedTimeOfDay;
}

final parsedDateTime = widget.booking.dateOnly!
.addLocalTimeOfDay(parsedTimeOfDay);

if (parsedDateTime.isBefore(
widget.booking.dateOnly!.addLocalTimeOfDay(
_startTime ?? TimeOfDay.now(),
),
) ||
parsedDateTime.isAfter(
widget.booking.dateOnly!
.addLocalTimeOfDay(kTimeTableEndTime),
)) {
return appLocalizations.enterValidRange;
}

if (_booking.cabin?.bookingCollection
.bookingsOverlapWith(_booking) ??
false) {
return appLocalizations.occupied;
}

return null;
},
autovalidateMode: AutovalidateMode.always,
),
),
],
Expand Down
12 changes: 6 additions & 6 deletions lib/widgets/cabin/cabin_dropdown.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,26 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:provider/provider.dart';

class CabinDropdown extends StatelessWidget {
final String value;
final void Function(String?)? onChanged;
final Cabin cabin;
final void Function(Cabin?)? onChanged;

const CabinDropdown({super.key, required this.value, this.onChanged});
const CabinDropdown({super.key, required this.cabin, this.onChanged});

@override
Widget build(BuildContext context) {
return Consumer<CabinCollection>(
builder: (context, cabinCollection, child) {
return DropdownButtonFormField<String>(
return DropdownButtonFormField<Cabin>(
items: [
for (final cabin in cabinCollection.cabins)
DropdownMenuItem(
value: cabin.id,
value: cabin,
child: Text(
'${AppLocalizations.of(context)!.cabin} ${cabin.number}',
),
),
],
value: value,
value: cabin,
onChanged: onChanged,
isExpanded: true,
);
Expand Down

0 comments on commit 3b5b404

Please sign in to comment.