created alram form widget placeholders

This commit is contained in:
2026-07-17 16:58:05 +02:00
parent c7ff39e55c
commit 3ceb0896a4
6 changed files with 218 additions and 41 deletions
+97 -40
View File
@@ -1,11 +1,16 @@
import 'package:flutter/material.dart';
import '../app_theme.dart';
import '../model/alarm.dart';
import '../model/callback_models/create_alarm_request.dart';
import '../model/callback_models/create_fixed_time_alarm_request.dart';
import '../model/callback_models/create_location_alarm_request.dart';
import '../model/callback_models/create_task_request.dart';
import '../model/extensions/controller_context.dart';
import '../model/task.dart';
import '../service/controllers/task_controller.dart';
import '../service/tools.dart';
import '../widgets/alarm_widgets/alarm_form_widget.dart';
import '../widgets/time_selector.dart';
class TaskEditPage extends StatefulWidget {
@@ -32,6 +37,7 @@ class _TaskEditPageState extends State<TaskEditPage> {
final formKey = GlobalKey<FormState>(debugLabel: 'taskEditFormKey');
bool didFormChange = false;
bool isDueTimeEnabled = false;
final List<CreateAlarmRequest> alarms = [];
@override
void didChangeDependencies() {
@@ -80,46 +86,84 @@ class _TaskEditPageState extends State<TaskEditPage> {
padding: EdgeInsets.symmetric(
horizontal: MediaQuery.of(context).size.width * 0.05,
),
child: Column(
spacing: AppTheme.formColumnSpacing,
children: [
SizedBox(height: 6),
TextFormField(
autofocus: true,
controller: titleController,
decoration: InputDecoration(label: Text('Title')),
keyboardType: TextInputType.text,
textInputAction: TextInputAction.next,
),
TextFormField(
controller: descriptionController,
decoration: InputDecoration(label: Text('Description')),
keyboardType: TextInputType.multiline,
textInputAction: TextInputAction.newline,
minLines: 3,
maxLines: 10,
),
TimeSelector(
initialDueDateTime: task?.due,
nextFocusNode: categoryFocusNode,
dueDateController: dueDateController,
dueTimeController: dueTimeController,
formKey: formKey,
),
TextFormField(
focusNode: categoryFocusNode,
controller: categoryController,
decoration: InputDecoration(label: Text('Category')),
keyboardType: TextInputType.text,
textInputAction: TextInputAction.next,
),
TextFormField(
controller: urlController,
decoration: InputDecoration(label: Text('Url')),
keyboardType: TextInputType.text,
textInputAction: TextInputAction.next,
),
],
child: SingleChildScrollView(
child: Column(
spacing: AppTheme.formColumnSpacing,
children: [
SizedBox(height: 6),
TextFormField(
autofocus: true,
controller: titleController,
decoration: InputDecoration(label: Text('Title')),
keyboardType: TextInputType.text,
textInputAction: TextInputAction.next,
),
TextFormField(
controller: descriptionController,
decoration: InputDecoration(label: Text('Description')),
keyboardType: TextInputType.multiline,
textInputAction: TextInputAction.newline,
minLines: 3,
maxLines: 10,
),
TimeSelector(
initialDueDateTime: task?.due,
nextFocusNode: categoryFocusNode,
dueDateController: dueDateController,
dueTimeController: dueTimeController,
formKey: formKey,
),
TextFormField(
focusNode: categoryFocusNode,
controller: categoryController,
decoration: InputDecoration(label: Text('Category')),
keyboardType: TextInputType.text,
textInputAction: TextInputAction.next,
),
TextFormField(
controller: urlController,
decoration: InputDecoration(label: Text('Url')),
keyboardType: TextInputType.text,
textInputAction: TextInputAction.next,
),
Text(
'Alarms',
style: Theme.of(context).textTheme.headlineLarge,
),
Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
spacing: AppTheme.formColumnSpacing,
children: [
ElevatedButton.icon(
onPressed: () => onAddAlarmPressed(AlarmType.timeFixed),
label: Text('Fixed Time'),
icon: Icon(Icons.alarm_add),
),
ElevatedButton.icon(
onPressed: () =>
onAddAlarmPressed(AlarmType.timeRelative),
label: Text('Relative Time'),
icon: Icon(Icons.timer_outlined),
),
ElevatedButton.icon(
onPressed: () => onAddAlarmPressed(AlarmType.location),
label: Text('Location'),
icon: Icon(Icons.location_on),
),
for (final (index, alarm) in alarms.indexed)
AlarmForm(
request: alarm,
onChanged: (updated) {
setState(() {
alarms[index] = updated;
});
},
),
],
),
],
),
),
),
),
@@ -174,4 +218,17 @@ class _TaskEditPageState extends State<TaskEditPage> {
});
}
}
void onAddAlarmPressed(AlarmType alarmType) {
switch (alarmType) {
case AlarmType.location:
alarms.add(CreateLocationAlarmRequest());
case AlarmType.timeFixed:
alarms.add(CreateFixedTimeAlarmRequest());
case AlarmType.timeRelative:
alarms.add(CreateFixedTimeAlarmRequest());
}
setState(() {});
}
}
@@ -0,0 +1,40 @@
import 'package:flutter/material.dart';
import '../../model/alarm.dart' show AlarmType;
import '../../model/callback_models/create_alarm_request.dart';
import '../../model/callback_models/create_fixed_time_alarm_request.dart';
import '../../model/callback_models/create_location_alarm_request.dart';
import '../../model/callback_models/create_relative_time_alarm_request.dart';
import 'fixed_time_alarm_form.dart';
import 'location_alarm_form.dart';
import 'relative_time_alarm_form.dart';
class AlarmForm extends StatelessWidget {
const AlarmForm({super.key, required this.request, required this.onChanged});
final CreateAlarmRequest request;
final ValueChanged<CreateAlarmRequest> onChanged;
@override
Widget build(BuildContext context) {
switch (request.alarmType) {
case AlarmType.timeFixed:
return FixedTimeAlarmForm(
request: request as CreateFixedTimeAlarmRequest,
onChanged: onChanged,
);
case AlarmType.timeRelative:
return RelativeTimeAlarmForm(
request: request as CreateRelativeTimeAlarmRequest,
onChanged: onChanged,
);
case AlarmType.location:
return LocationAlarmForm(
request: request as CreateLocationAlarmRequest,
onChanged: onChanged,
);
}
}
}
@@ -0,0 +1,19 @@
import 'package:flutter/material.dart';
import '../../model/callback_models/create_alarm_request.dart';
import '../../model/callback_models/create_fixed_time_alarm_request.dart';
class FixedTimeAlarmForm extends StatelessWidget {
const FixedTimeAlarmForm({
super.key,
required this.request,
required this.onChanged,
});
final CreateFixedTimeAlarmRequest request;
final ValueChanged<CreateAlarmRequest> onChanged;
@override
Widget build(BuildContext context) {
return const Placeholder();
}
}
@@ -0,0 +1,19 @@
import 'package:flutter/material.dart';
import '../../model/callback_models/create_alarm_request.dart';
import '../../model/callback_models/create_location_alarm_request.dart';
class LocationAlarmForm extends StatelessWidget {
const LocationAlarmForm({
super.key,
required this.request,
required this.onChanged,
});
final CreateLocationAlarmRequest request;
final ValueChanged<CreateAlarmRequest> onChanged;
@override
Widget build(BuildContext context) {
return const Placeholder();
}
}
@@ -0,0 +1,19 @@
import 'package:flutter/material.dart';
import '../../model/callback_models/create_alarm_request.dart';
import '../../model/callback_models/create_relative_time_alarm_request.dart';
class RelativeTimeAlarmForm extends StatelessWidget {
const RelativeTimeAlarmForm({
super.key,
required this.request,
required this.onChanged,
});
final CreateRelativeTimeAlarmRequest request;
final ValueChanged<CreateAlarmRequest> onChanged;
@override
Widget build(BuildContext context) {
return const Placeholder();
}
}
+24 -1
View File
@@ -12,6 +12,7 @@ class TimeSelector extends StatefulWidget {
required this.dueDateController,
required this.dueTimeController,
this.formKey,
this.onChanged,
});
final DateTime? initialDueDateTime;
@@ -19,6 +20,7 @@ class TimeSelector extends StatefulWidget {
final FocusNode? nextFocusNode;
final TextEditingController dueDateController;
final TextEditingController dueTimeController;
final void Function(DateTime dateTime)? onChanged;
@override
State<TimeSelector> createState() => _TimeSelectorState();
@@ -48,7 +50,18 @@ class _TimeSelectorState extends State<TimeSelector> {
child: TextFormField(
focusNode: dueDateFocusNode,
controller: widget.dueDateController,
onChanged: maybeEnableDueTime,
onChanged: (value) {
maybeEnableDueTime(value);
if (dateTimeValidator(value) == null &&
widget.onChanged != null) {
final dateTime = DateTime.tryParse(
'$value ${widget.dueTimeController.text}'.trim(),
);
if (dateTime != null) {
widget.onChanged!(dateTime);
}
}
},
onFieldSubmitted: (_) {
isDueTimeEnabled
? dueDateFocusNode.nextFocus()
@@ -85,6 +98,16 @@ class _TimeSelectorState extends State<TimeSelector> {
onFieldSubmitted: (_) => dueTimeFocusNode.nextFocus(),
controller: widget.dueTimeController,
enabled: isDueTimeEnabled,
onChanged: (value) {
if (timeValidator(value) == null && widget.onChanged != null) {
final dateTime = DateTime.tryParse(
'${widget.dueDateController.text} $value'.trim(),
);
if (dateTime != null) {
widget.onChanged!(dateTime);
}
}
},
decoration: InputDecoration(
label: Text('Due Time'),
suffixIcon: IconButton(