feat: polish phase 7 forms and schedules
This commit is contained in:
147
lib/features/schedules/schedule_form_logic.dart
Normal file
147
lib/features/schedules/schedule_form_logic.dart
Normal file
@@ -0,0 +1,147 @@
|
||||
class ScheduleWeekdayOption {
|
||||
final int backendValue;
|
||||
final String shortLabel;
|
||||
final String fullLabel;
|
||||
|
||||
const ScheduleWeekdayOption({
|
||||
required this.backendValue,
|
||||
required this.shortLabel,
|
||||
required this.fullLabel,
|
||||
});
|
||||
}
|
||||
|
||||
const scheduleWeekdayOptions = <ScheduleWeekdayOption>[
|
||||
ScheduleWeekdayOption(
|
||||
backendValue: 1,
|
||||
shortLabel: 'Пн',
|
||||
fullLabel: 'понедельник',
|
||||
),
|
||||
ScheduleWeekdayOption(
|
||||
backendValue: 2,
|
||||
shortLabel: 'Вт',
|
||||
fullLabel: 'вторник',
|
||||
),
|
||||
ScheduleWeekdayOption(backendValue: 3, shortLabel: 'Ср', fullLabel: 'среда'),
|
||||
ScheduleWeekdayOption(
|
||||
backendValue: 4,
|
||||
shortLabel: 'Чт',
|
||||
fullLabel: 'четверг',
|
||||
),
|
||||
ScheduleWeekdayOption(
|
||||
backendValue: 5,
|
||||
shortLabel: 'Пт',
|
||||
fullLabel: 'пятница',
|
||||
),
|
||||
ScheduleWeekdayOption(
|
||||
backendValue: 6,
|
||||
shortLabel: 'Сб',
|
||||
fullLabel: 'суббота',
|
||||
),
|
||||
ScheduleWeekdayOption(
|
||||
backendValue: 0,
|
||||
shortLabel: 'Вс',
|
||||
fullLabel: 'воскресенье',
|
||||
),
|
||||
];
|
||||
|
||||
DateTime defaultOnceScheduleTime({DateTime? now}) {
|
||||
final base = now ?? DateTime.now();
|
||||
final candidate = base.add(const Duration(hours: 4));
|
||||
final roundedMinute = ((candidate.minute + 4) ~/ 5) * 5;
|
||||
final normalized = DateTime(
|
||||
candidate.year,
|
||||
candidate.month,
|
||||
candidate.day,
|
||||
candidate.hour,
|
||||
roundedMinute,
|
||||
);
|
||||
return normalized.isAfter(base)
|
||||
? normalized
|
||||
: normalized.add(const Duration(minutes: 5));
|
||||
}
|
||||
|
||||
String? validateOnceSchedule(DateTime? scheduledAt, {DateTime? now}) {
|
||||
if (scheduledAt == null) {
|
||||
return 'Выберите дату и время';
|
||||
}
|
||||
final threshold = (now ?? DateTime.now()).add(const Duration(minutes: 1));
|
||||
if (!scheduledAt.isAfter(threshold)) {
|
||||
return 'Нужна дата хотя бы на минуту вперёд';
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
String? validateCronSchedule({
|
||||
required int? hour,
|
||||
required int? minute,
|
||||
required Set<int> weekdays,
|
||||
}) {
|
||||
if (hour == null || hour < 0 || hour > 23) {
|
||||
return 'Час должен быть от 0 до 23';
|
||||
}
|
||||
if (minute == null || minute < 0 || minute > 59) {
|
||||
return 'Минута должна быть от 0 до 59';
|
||||
}
|
||||
if (weekdays.isEmpty) {
|
||||
return 'Выберите хотя бы один день недели';
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
String serializeCronWeekdays(Set<int> weekdays) {
|
||||
if (weekdays.length == scheduleWeekdayOptions.length) {
|
||||
return '*';
|
||||
}
|
||||
final sorted = weekdays.toList()..sort();
|
||||
return sorted.join(',');
|
||||
}
|
||||
|
||||
String describeCronWeekdays(Set<int> weekdays) {
|
||||
if (weekdays.isEmpty) {
|
||||
return 'дни не выбраны';
|
||||
}
|
||||
if (weekdays.length == scheduleWeekdayOptions.length) {
|
||||
return 'каждый день';
|
||||
}
|
||||
final weekdaySet = weekdays.toSet();
|
||||
final selected = scheduleWeekdayOptions
|
||||
.where((option) => weekdaySet.contains(option.backendValue))
|
||||
.map((option) => option.shortLabel)
|
||||
.toList();
|
||||
return selected.join(', ');
|
||||
}
|
||||
|
||||
String describeCronWeekdaysExpression(String? value) {
|
||||
if (value == null || value.isEmpty || value == '*') {
|
||||
return 'каждый день';
|
||||
}
|
||||
|
||||
final weekdays = value
|
||||
.split(',')
|
||||
.map((item) => int.tryParse(item.trim()))
|
||||
.whereType<int>()
|
||||
.toSet();
|
||||
if (weekdays.isEmpty) {
|
||||
return value;
|
||||
}
|
||||
|
||||
return describeCronWeekdays(weekdays);
|
||||
}
|
||||
|
||||
String formatLocalScheduleDateTime(DateTime value) {
|
||||
String pad(int number) => number.toString().padLeft(2, '0');
|
||||
return '${pad(value.day)}.${pad(value.month)}.${value.year} ${pad(value.hour)}:${pad(value.minute)}';
|
||||
}
|
||||
|
||||
String formatRunAtLabel(String? value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'время не указано';
|
||||
}
|
||||
|
||||
final parsed = DateTime.tryParse(value);
|
||||
if (parsed == null) {
|
||||
return value;
|
||||
}
|
||||
|
||||
return formatLocalScheduleDateTime(parsed.toLocal());
|
||||
}
|
||||
Reference in New Issue
Block a user