import 'dart:math'; import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import 'package:nextcloud_reminder/repeating_task.dart'; import 'package:nextcloud_reminder/types/tasks.dart'; class ScrollTable extends StatefulWidget { ScrollTable({super.key, required this.title, required this.deleteCallback}); // This class is the configuration for the state. It holds the values (in this // case the title) provided by the parent (in this case the App widget) and // used by the build method of the State. Fields in a Widget subclass are // always marked "final". final String title; final _ScrollTableState _internalState = _ScrollTableState(); final ValueChanged deleteCallback; @override State createState() => _internalState; void addTask(RepeatingTask task) { _internalState.addTask(task); } } class _ScrollTableState extends State { final List _content = []; final _contentStart = DateTime.now(); addTask(RepeatingTask task) { setState(() { _content.add(task); }); } removeTask(RepeatingTask task) { setState(() { _content.remove(task); }); widget.deleteCallback(task); } Future _showDetailsAndRemoveTask(BuildContext context, RepeatingTask t) { return showDialog(context: context, barrierDismissible: true, builder: (BuildContext context) { return AlertDialog( title: const Text("Task details"), content: SingleChildScrollView( child: ListBody( children: [ Text(t.task.title), Text("Projects: ${t.task.projects.isEmpty ? "none" : t.task.projects.join(", ")}"), Text("Contexts: ${t.task.contexts.isEmpty ? "none" : t.task.contexts.join(", ")}"), Padding(padding: const EdgeInsets.only(top: 16), child: Text(t.task.meta.isEmpty ? "" : "Meta:", style: Theme.of(context).textTheme.bodyLarge,) ), ] + List.of(t.task.meta.entries.map((e) => Text("${e.key}: ${e.value}"))), ), ), actions: [ TextButton(onPressed: () { removeTask(t); Navigator.of(context).pop(); }, style: TextButton.styleFrom(foregroundColor: Theme .of(context) .errorColor), child: const Text("remove"),), TextButton(onPressed: () => Navigator.of(context).pop(), child: const Text("close")), ] ); }); } Widget _todoHeader(BuildContext context) { return Container( width: 200, height: 60, alignment: Alignment.bottomLeft, padding: const EdgeInsets.only(left: 8, right: 8, bottom: 12), decoration: BoxDecoration(color: Theme.of(context).colorScheme.background), child: Text("TODO", style: Theme.of(context).textTheme.titleSmall?.copyWith(color: Theme.of(context).colorScheme.primary),), ); } Widget _datesHeader(BuildContext context) { return Row( children: List.generate(10, (i) => Container( width: 60, height: 60, alignment: Alignment.bottomCenter, padding: const EdgeInsets.only(left: 8, right: 8, bottom: 16), decoration: BoxDecoration(color: Theme.of(context).colorScheme.background), child: Transform.rotate(angle: -pi/3, child: Text(DateFormat.Md().format(_contentStart.add(Duration(days: i))), style: Theme.of(context).textTheme.titleMedium?.copyWith(color: Theme.of(context).colorScheme.primary),), ) )) ); } List _buildTitles(BuildContext context) { return List.from(_content.map((RepeatingTask t) => Container( alignment: Alignment.centerLeft, width: 200.0, height: 60.0, margin: const EdgeInsets.only(top: 1), decoration: BoxDecoration(color: Theme.of(context).canvasColor, border: Border(bottom: BorderSide(color: Theme.of(context).colorScheme.background, width: 1),)), child: SizedBox(width: 200, child: TextButton( onPressed: () => _showDetailsAndRemoveTask(context,t), style: const ButtonStyle(alignment: AlignmentDirectional.centerStart), child: Text(t.task.title, softWrap: true, textAlign: TextAlign.left, style: Theme.of(context).textTheme.titleSmall, ) )), ) ) ); } @override Widget build(BuildContext context) { return SingleChildScrollView( child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, //TODO: Text in container wie bei _buildTitles oben und width/height/margin/etc. festnageln. children: List.from([_todoHeader(context)]) + _buildTitles(context), ), Flexible( child: SingleChildScrollView( scrollDirection: Axis.horizontal, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [_datesHeader(context)] + List.from(_content), ), ), ) ], ) ); } }