import 'package:flutter/material.dart'; import 'package:spreadsheet_table/spreadsheet_table.dart'; import 'package:pluto_grid/pluto_grid.dart'; import 'package:ltx_flutter/appwrite/auth_api.dart'; import 'package:ltx_flutter/appwrite/database_api.dart'; import 'package:provider/provider.dart'; import 'package:appwrite/models.dart'; import 'package:intl/intl.dart'; class TablePage extends StatefulWidget { const TablePage({Key? key}) : super(key: key); @override _TablePageState createState() => _TablePageState(); } class _TablePageState extends State { final database = DatabaseAPI(); late List? entries = []; AuthStatus authStatus = AuthStatus.uninitialized; @override void initState() { super.initState(); final AuthAPI appwrite = context.read(); authStatus = appwrite.status; loadEntries(); } loadEntries() async { try { final value = await database.getEntries(limit: 25); setState(() { entries = value.documents; }); } catch (e) { print(e); } } String formatDate({String format = "", String? dateISO}) { final DateFormat dateFormatter = DateFormat(format); final date = dateISO!.isEmpty ? DateTime.now() : DateTime.parse(dateISO); return dateFormatter.format(date); } List hourCols = List.generate(24, (i) => i).map((e) { var meridien = "AM"; var hour = 12; if (e > 12) { hour = e - 12; } else if (e > 0) { hour = e; } if (e > 11) { meridien = "PM"; } var hourTitle = "${hour.toString()} $meridien"; return PlutoColumn( title: hourTitle, field: "hours[$e]", type: PlutoColumnType.number(), width: 70, enableContextMenu: false, enableDropToResize: false, textAlign: PlutoColumnTextAlign.center, titleTextAlign: PlutoColumnTextAlign.center, ); }).toList(); late List columns = [ PlutoColumn( title: 'DATE', field: 'date', type: PlutoColumnType.text(), readOnly: true, width: 70, enableContextMenu: false, enableDropToResize: false, textAlign: PlutoColumnTextAlign.center, titleTextAlign: PlutoColumnTextAlign.center, frozen: PlutoColumnFrozen.start, ), PlutoColumn( title: 'DAY', field: 'day', type: PlutoColumnType.text(), readOnly: true, width: 53, enableContextMenu: false, enableDropToResize: false, ), ] + hourCols + [ PlutoColumn( title: 'Mood', field: 'mood', width: 60, textAlign: PlutoColumnTextAlign.center, type: PlutoColumnType.text(), enableContextMenu: false, enableDropToResize: false, ), PlutoColumn( title: 'Comments', field: 'comments', type: PlutoColumnType.text(), enableContextMenu: false, enableDropToResize: false, ), ]; late List rows = entries!.map((e) { var cells = { 'date': PlutoCell( value: formatDate( format: "MM/DD", dateISO: e.data['date'], ), ), 'day': PlutoCell( value: formatDate( format: "E", dateISO: e.data['date'], ), ), 'mood': PlutoCell(value: e.data['mood']), 'comments': PlutoCell(value: e.data['comments']), }; var hours = {}; for (int i = 0; i < 24; i++) { hours.putIfAbsent( "hours[$i]", () => PlutoCell( value: e.data['hours'][i], ), ); } cells.addEntries(hours.entries); return PlutoRow( cells: cells, ); }).toList(); /// columnGroups that can group columns can be omitted. final List columnGroups = []; /// [PlutoGridStateManager] has many methods and properties to dynamically manipulate the grid. /// You can manipulate the grid dynamically at runtime by passing this through the [onLoaded] callback. late final PlutoGridStateManager stateManager; @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.all(10), child: Column( children: [ Expanded( child: entries!.isEmpty ? Center(child: const CircularProgressIndicator()) : Scaffold( body: InteractiveViewer( child: PlutoGrid( columns: columns, rows: rows, columnGroups: columnGroups, onLoaded: (PlutoGridOnLoadedEvent event) { stateManager = event.stateManager; }, onChanged: (PlutoGridOnChangedEvent event) { print(event); }, configuration: const PlutoGridConfiguration.dark( style: PlutoGridStyleConfig.dark( cellTextStyle: TextStyle(fontFamily: "monospace"), rowHeight: 20, gridBorderColor: Colors.transparent, enableCellBorderHorizontal: false, enableCellBorderVertical: false, ), ), ), ), )), // Expanded(child: DiagnosticsWidget(entries: entries)), ], ), ); } } class DiagnosticsWidget extends StatelessWidget { final List? entries; const DiagnosticsWidget({ super.key, this.entries, }); @override Widget build(BuildContext context) { return ListView( children: [ ListTile( leading: Icon(Icons.date_range_outlined), title: Text("Entries"), subtitle: Text("${entries?.length}"), ), ], ); } } class TableWidget extends StatelessWidget { TableWidget({super.key, this.entries}); final List? entries; final DateFormat dateFormatter = DateFormat('MM/dd'); final DateFormat dayFormatter = DateFormat('E'); final List columns = []; final List rows = []; @override Widget build(BuildContext context) { return Text("moot"); } } class SpreadsheetWidget extends StatelessWidget { SpreadsheetWidget({super.key, this.entries}); final List? entries; final DateFormat dateFormatter = DateFormat('MM/dd'); final DateFormat dayFormatter = DateFormat('E'); @override Widget build(BuildContext context) { return SpreadsheetTable( cellWidth: 80, rowsCount: entries!.length, colCount: 27, cellBuilder: (_, int row, int col) { var entry = entries?[row]; var date = DateTime.parse(entry?.data['date']); var day = dayFormatter.format(date); List hours = entry?.data['hours']; if (col == 0) { return Center(child: Text(day)); } else if (col > 0 && col < 25) { return Center(child: Text(hours[col - 1].toString())); } else { return Center(child: Text('')); } }, legendBuilder: (_) => Center(child: Text("Date".toUpperCase())), colHeaderBuilder: (_, index) { var cellText = ""; if (index == 0) { cellText = "Day"; } else if (index == 1) { cellText = "12 AM"; } else if (index > 1 && index < 25) { var meridien = "AM"; var hour = index - 1; if (index > 12) { meridien = "PM"; } if (index > 13) { hour = hour - 12; } cellText = "${hour.toString()} $meridien"; } else if (index == 25) { cellText = "Mood"; } else if (index == 26) { cellText = "Comments"; } return Center(child: Text(cellText.toUpperCase())); }, rowHeaderBuilder: (_, index) { var date = DateTime.parse(entries![index].data["date"]); var formattedDate = dateFormatter.format(date); return Center(child: Text(formattedDate)); }, ); } }