fixed designs and flow
This commit is contained in:
@@ -1,21 +1,97 @@
|
||||
enum DayBlock { morning, afternoon, evening }
|
||||
/// What a worker has said about a given day.
|
||||
///
|
||||
/// Three states rather than an on/off switch, because "I can work" and "I want
|
||||
/// work" are different answers and Auto-Match treats them differently: an
|
||||
/// available day is one it may fill, a preferred day is one it should fill
|
||||
/// first.
|
||||
enum DayAvailability { available, prefers, unavailable }
|
||||
|
||||
extension DayBlockX on DayBlock {
|
||||
extension DayAvailabilityX on DayAvailability {
|
||||
String get label => switch (this) {
|
||||
DayBlock.morning => 'Morning',
|
||||
DayBlock.afternoon => 'Afternoon',
|
||||
DayBlock.evening => 'Evening',
|
||||
DayAvailability.available => 'Available',
|
||||
DayAvailability.prefers => 'Prefers to work',
|
||||
DayAvailability.unavailable => 'Unavailable',
|
||||
};
|
||||
|
||||
String get window => switch (this) {
|
||||
DayBlock.morning => '04:00 - 12:00',
|
||||
DayBlock.afternoon => '12:00 - 18:00',
|
||||
DayBlock.evening => '18:00 - 24:00',
|
||||
/// The line under the option, in the picker.
|
||||
String get blurb => switch (this) {
|
||||
DayAvailability.available => 'Can be scheduled any time',
|
||||
DayAvailability.prefers => 'Wants shifts — optionally within a time window',
|
||||
DayAvailability.unavailable => 'Marked off (vacation, sick, personal)',
|
||||
};
|
||||
|
||||
int get hours => switch (this) {
|
||||
DayBlock.morning => 8,
|
||||
DayBlock.afternoon => 6,
|
||||
DayBlock.evening => 6,
|
||||
/// The line under the date, once the day is set.
|
||||
String get summary => switch (this) {
|
||||
DayAvailability.available => 'Can be scheduled any time',
|
||||
DayAvailability.prefers => 'Wants shifts',
|
||||
DayAvailability.unavailable => 'Not available',
|
||||
};
|
||||
}
|
||||
|
||||
/// The hours a worker would rather be given, on a day they want work.
|
||||
///
|
||||
/// Both ends are optional and independent: "from 6pm, any end" is a normal
|
||||
/// thing to want, and forcing a full range would make the worker invent one.
|
||||
/// Null at both ends means any time, which is also the default.
|
||||
class PreferredWindow {
|
||||
const PreferredWindow({this.from, this.to});
|
||||
|
||||
/// Hour of the day, 0-23. Null is "any time".
|
||||
final int? from;
|
||||
final int? to;
|
||||
|
||||
static const any = PreferredWindow();
|
||||
|
||||
bool get isAnyTime => from == null && to == null;
|
||||
|
||||
/// How the window reads on its own, as a label.
|
||||
String get label {
|
||||
if (isAnyTime) return 'Any time';
|
||||
if (from != null && to != null) return '${_hhmm(from!)} - ${_hhmm(to!)}';
|
||||
if (from != null) return 'From ${_hhmm(from!)}';
|
||||
return 'Until ${_hhmm(to!)}';
|
||||
}
|
||||
|
||||
/// How the window reads inside a sentence — "look for shifts $sentence
|
||||
/// first". The label does not survive being dropped mid-sentence: "look for
|
||||
/// From 09:00 first" is not English.
|
||||
String get sentence {
|
||||
if (isAnyTime) return 'at any time';
|
||||
if (from != null && to != null) {
|
||||
return 'between ${_hhmm(from!)} and ${_hhmm(to!)}';
|
||||
}
|
||||
if (from != null) return 'from ${_hhmm(from!)}';
|
||||
return 'until ${_hhmm(to!)}';
|
||||
}
|
||||
|
||||
PreferredWindow copyWith({
|
||||
int? from,
|
||||
int? to,
|
||||
bool clearFrom = false,
|
||||
bool clearTo = false,
|
||||
}) => PreferredWindow(
|
||||
from: clearFrom ? null : (from ?? this.from),
|
||||
to: clearTo ? null : (to ?? this.to),
|
||||
);
|
||||
|
||||
static String _hhmm(int hour) => '${hour.toString().padLeft(2, '0')}:00';
|
||||
}
|
||||
|
||||
/// A day's answer: the status, and the window if one was given.
|
||||
class DayPlan {
|
||||
const DayPlan({
|
||||
this.status = DayAvailability.unavailable,
|
||||
this.window = PreferredWindow.any,
|
||||
});
|
||||
|
||||
final DayAvailability status;
|
||||
|
||||
/// Only meaningful while [status] is [DayAvailability.prefers]; kept across
|
||||
/// a status change so flipping away and back does not lose the hours.
|
||||
final PreferredWindow window;
|
||||
|
||||
bool get isSet => status != DayAvailability.unavailable;
|
||||
|
||||
DayPlan copyWith({DayAvailability? status, PreferredWindow? window}) =>
|
||||
DayPlan(status: status ?? this.status, window: window ?? this.window);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user