import 'package:date_field/date_field.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:gap/gap.dart'; import 'package:nextcloud_reminder/repeating_task.dart'; import 'package:nextcloud_reminder/types/repeat.dart'; import 'package:nextcloud_reminder/types/tasks.dart'; import 'package:tuple/tuple.dart'; class AddTaskWidget extends StatefulWidget { const AddTaskWidget({super.key, this.restorationId, required this.onSave}); final ValueChanged onSave; final String? restorationId; @override State createState() => _AddTaskWidgetState(); } //TODO: make _repeat changeable. class _AddTaskWidgetState extends State { final _formKey = GlobalKey(); final _titleController = TextEditingController(); static _emptyRepetition() { return Tuple2(TextEditingController(text: "1"), ValueNotifier(DateInterval.daily)); } final List>> _repeatEveryController = [_emptyRepetition()]; DateTime _beginDate = DateTime.now(); @override void dispose() { _titleController.dispose(); super.dispose(); } String _prettyInterval(DateInterval d) { switch (d) { case DateInterval.daily: return "day"; case DateInterval.weekly: return "week"; case DateInterval.monthly: return "month"; case DateInterval.monday: return "monday"; case DateInterval.tuesday: return "tuesday"; case DateInterval.wednesday: return "wednesday"; case DateInterval.thursday: return "thursday"; case DateInterval.friday: return "friday"; case DateInterval.saturday: return "saturday"; case DateInterval.sunday: return "sunday"; case DateInterval.dayOfMonth: return "day of the month"; case DateInterval.dayOfYear: return "day of the year"; } } Widget _repeatBuilder(BuildContext context, Tuple2> data) { return IntrinsicHeight(child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ SizedBox( width: 200, child: TextFormField( controller: data.item1, decoration: InputDecoration( prefix: const Text("Repeat every "), suffix: () { if (data.item1.value.text.isEmpty) return const Text(""); switch (data.item1.value.text.substring(data.item1.value.text.length - 1)) { case "1": return const Text("st"); case "2": return const Text("nd"); case "3": return const Text("rd"); default: return const Text("th"); }}(), border: const OutlineInputBorder() ), textAlign: TextAlign.end, keyboardType: const TextInputType.numberWithOptions(signed: false, decimal: false), inputFormatters: [FilteringTextInputFormatter.digitsOnly], onChanged: (_) {setState(() { //nothing just rerender. });}, ), ), const Gap(4), Expanded( //padding: const EdgeInsets.only(left: 30, right: 20), child: DropdownButtonFormField( decoration: const InputDecoration( border: OutlineInputBorder(), ), items: DateInterval.values.map((v) => DropdownMenuItem(value: v, child: Text(_prettyInterval(v)))).toList(), onChanged: (v) => setState(() { data.item2.value = v ?? data.item2.value; }), value: data.item2.value, ), ), PreferredSize( preferredSize: const Size.square(40), child: IconButton( alignment: Alignment.topCenter, onPressed: () => setState(() { _repeatEveryController.remove(data); }), icon: Icon(Icons.remove, color: Theme.of(context).errorColor,) )), ], )); } Widget _addPadding(Widget w) { return Padding(padding: EdgeInsets.all(4), child: w); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Add new repeating Task') ), body: Form( key: _formKey, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ _addPadding(TextFormField( // The validator receives the text that the user has entered. validator: (value) { if (value == null || value.isEmpty) { return 'Please enter a name'; } return null; }, autofocus: true, controller: _titleController, decoration: const InputDecoration( labelText: "Taskname" ), )), _addPadding(DateTimeField( onDateSelected: (v) => setState(() { _beginDate = v; }), selectedDate: _beginDate, decoration: const InputDecoration( suffixIcon: Icon(Icons.event_note), labelText: "Begin" ), mode: DateTimeFieldPickerMode.date, )), ] + _repeatEveryController.map((c) => _addPadding(_repeatBuilder(context,c))).toList() + [ _addPadding(_addPadding(Row( children: [ ElevatedButton(onPressed: () => setState(() { _repeatEveryController.add(_emptyRepetition()); }), child: const Text("add repetition")), Expanded(child: Container()), ElevatedButton( onPressed: () { // Validate returns true if the form is valid, or false otherwise. if (_formKey.currentState!.validate()) { // If the form is valid, display a snackbar. In the real world, // you'd often call a server or save the information in a database. ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Task added.')), ); var repeats = _repeatEveryController.map((e) => RepeatInterval(interval: e.item2.value, every: int.parse(e.item1.text))).toList(); var meta = repeats.map((e) => e.toString()).join("/"); widget.onSave(RepeatingTask( task: TaskExtra( title: _titleController.text, begin: _beginDate, meta: {"repeat": meta}, repeat: repeats, ) )); Navigator.pop(context); } }, child: const Text('Submit'), ), ] ))), ], ), ) ); } }