import 'package:ltx_flutter/appwrite/categories_api.dart'; import 'package:ltx_flutter/appwrite/database_api.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:intl/intl.dart'; import 'package:appwrite/models.dart'; String formatDate({String format = "", String? dateISO}) { final DateFormat dateFormatter = DateFormat(format); final date = dateISO!.isEmpty ? DateTime.now() : DateTime.parse(dateISO); return dateFormatter.format(date); } String hourString(int e) { var meridien = "AM"; var hour = 12; if (e > 12) { hour = e - 12; } else if (e > 0) { hour = e; } if (e > 11) { meridien = "PM"; } return "${hour.toString()} $meridien"; } List generateHours(entry, bool edit) { if (entry == null) { return [Center(child: RefreshProgressIndicator())]; } List hours = entry.data['hours']; // print(hours); List reduced = []; int counter = 0; if (edit) { for (int val in hours) { if (reduced.isEmpty) { reduced.add({'val': val, 'num': 1, 'hour': counter}); } else { if (reduced.last['val'] == val) { reduced.last['num']++; reduced.last['hour'] = counter; } else { reduced.add({'val': val, 'num': 1, 'hour': counter}); } } counter++; } } else { for (int val in hours) { reduced.add({ 'hour': counter, 'val': val, 'num': 1, }); } } return reduced.map( (e) { double height = double.parse((e['num'] * 36).toString()); return Consumer( builder: (context, categories, child) { Category category = categories.lookUp(e['val'].toString()); return SizedBox( height: height, child: Card( color: category.backgroundColor, child: Padding( padding: const EdgeInsets.only(left: 10), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ e['num'] == 1 ? Center( child: Text( style: TextStyle(color: category.foregroundColor), hourString(e['hour'])), ) : Padding( padding: const EdgeInsets.only(top: 10, bottom: 10), child: Column( children: [ Text( style: TextStyle( color: category.foregroundColor), hourString(e['hour'] - e['num'] + 1)), Expanded( child: VerticalDivider( indent: 10, endIndent: 10, color: category.foregroundColor, width: 4, ), ), Text( style: TextStyle( color: category.foregroundColor), hourString(e['hour'] + 1)) ], ), ), Expanded( child: Center( child: Text( style: TextStyle(color: category.foregroundColor), category.name), ), ), ], ), ), ), ); }, ); }, ).toList(); } Color moodColor(mood) { if (mood == null) { return Colors.transparent; } if (mood >= 8) { return Colors.green; } if (mood > 5) { return Colors.blue; } if (mood == 5) { return Colors.yellow; } if (mood >= 3) { return Colors.amber; } else { return Colors.red; } } class TodayPage extends StatefulWidget { const TodayPage({Key? key}) : super(key: key); @override _TodayPageState createState() => _TodayPageState(); } class _TodayPageState extends State { @override Widget build(BuildContext context) { return LayoutBuilder( builder: (BuildContext context, BoxConstraints constraints) { if (constraints.maxWidth > 800) { return Text("Wide"); } else { return Consumer(builder: (context, database, child) { return database.ready ? NarrowView() : Center( child: CircularProgressIndicator( value: database.progress, )); }); } }); } } class NarrowView extends StatelessWidget { const NarrowView({ super.key, }); @override Widget build(BuildContext context) { return DefaultTabController( length: 4, initialIndex: 0, child: Column( children: [ TabBar( tabs: [ Tab(icon: Icon(Icons.calendar_view_day)), Tab(icon: Icon(Icons.calendar_view_week)), Tab(icon: Icon(Icons.calendar_view_month)), Tab(icon: Icon(Icons.all_inclusive)), ], ), Expanded( child: TabBarView( children: [ DayView(), Icon(Icons.directions_transit, size: 350), Icon(Icons.directions_car, size: 350), Icon(Icons.abc), ], ), ) ], ), ); } } class DayView extends StatefulWidget { const DayView({ super.key, }); @override State createState() => _DayViewState(); } class _DayViewState extends State { DateTime _date = DateTime.now(); late DatabaseAPI database; late CategoriesAPI categories; late List entries = []; late Document? dayEntry = null; late List hours = []; late num? mood = 0; late String comments = ""; @override void didChangeDependencies() { super.didChangeDependencies(); database = context.watch(); categories = context.watch(); entries = database.entries; } void _incrementDate(int amount) => _setDate(_date.add(Duration(days: amount))); void _setDate(DateTime? day) { if (day != null) { setState(() { _date = day; }); } } @override Widget build(BuildContext context) { List entries = database.entries; String formattedDate = formatDate( dateISO: _date.toIso8601String(), format: "yyyy-MM-dd", ); try { dayEntry = entries.singleWhere((element) => element.$id == formattedDate); String date = formatDate( format: "LLL d", dateISO: dayEntry?.data['date'].toString()); print("Got entry for $date"); } catch (e) { database.getOne(date: formattedDate).then((value) => dayEntry = value); } setState(() { if (dayEntry != null) { comments = dayEntry?.data["comments"]; mood = dayEntry?.data["mood"]; } }); TextEditingController commentsController = TextEditingController(text: comments); Widget moodWidget = mood == null ? Icon( size: 30, Icons.star_rate_outlined, color: Colors.black, ) : Text( style: TextStyle(fontSize: 20, color: Colors.black), mood.toString()); return Column( children: [ SizedBox( height: 20, ), Padding( padding: const EdgeInsets.all(8.0), child: GestureDetector( onTap: () => _setDate(DateTime.now()), onLongPress: () { showDatePicker( context: context, initialDate: _date, firstDate: DateTime.parse("2023-01-01"), lastDate: DateTime.now().add(Duration(days: 7)), ).then((value) => _setDate(value)); }, child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ IconButton( tooltip: "Previous day", icon: Icon(Icons.arrow_left), onPressed: () => _incrementDate(-1), ), SizedBox( width: 250, child: Text( textAlign: TextAlign.center, style: TextStyle( fontSize: 20, ), formatDate( format: 'EEEEE, LLLL dd, yyyy', dateISO: _date.toIso8601String()), ), ), IconButton( tooltip: "Next day", icon: Icon(Icons.arrow_right), onPressed: () => _incrementDate(1), ), ], ), ), ), Expanded( child: ListView( children: categories.ready ? generateHours(dayEntry, true) : [CircularProgressIndicator()], ), ), Padding( padding: const EdgeInsets.only(top: 30, right: 30, left: 10), child: Row( children: [ SizedBox(width: 10), SizedBox.square( dimension: 50, child: Container( color: moodColor(mood), child: Center(child: moodWidget), ), ), SizedBox(width: 30), Expanded( child: TextFormField( decoration: InputDecoration(hintText: "Comments"), smartQuotesType: SmartQuotesType.enabled, enableInteractiveSelection: true, controller: commentsController, ), ), SizedBox(width: 30), IconButton( tooltip: "Save", onPressed: () => print("Save"), icon: Icon(Icons.save), ) ], ), ), SizedBox(height: 30), ], ); } }