import 'package:appwrite/appwrite.dart'; import 'package:appwrite/models.dart'; import 'package:flutter/material.dart'; import 'package:ltx_flutter/appwrite/auth_api.dart'; import 'package:ltx_flutter/constants/constants.dart'; import 'package:intl/intl.dart'; class DatabaseAPI extends ChangeNotifier { Client client = Client(); late final Account account; late final Databases databases; late final Realtime realtime; final AuthAPI auth = AuthAPI(); late List _entries = []; bool _ready = false; // Getter methods List get entries => _entries; int get length => _entries.length; bool get ready => _ready; double get progress => length / total(); final DateFormat formatter = DateFormat('yyyy-MM-dd'); // Constructor DatabaseAPI() { init(); getAll(); subscribeRealtime(); } init() { client.setEndpoint(APPWRITE_URL).setProject(APPWRITE_PROJECT_ID); account = Account(client); databases = Databases(client); realtime = Realtime(client); } elDate(dynamic el) { return formatter.format(DateTime.parse(el.data['date'])); } sortByDate(entries) { return entries.sort( (a, b) => a.$id.compareTo(b.$id), ); } subscribeRealtime() { final subscription = realtime.subscribe( ['databases.$APPWRITE_DATABASE_ID.collections.$COLLECTION.documents']); print("Subscribed to realtime"); subscription.stream.listen((response) { String dateISO = formatter.format(DateTime.parse(response.payload['date'])); if (response.events.contains( 'databases.$APPWRITE_DATABASE_ID.collections.$COLLECTION.documents.*.update')) { // Entry was updated int entryIndex = _entries.indexWhere((element) => elDate(element) == dateISO); Document newEntry = _entries[entryIndex]; newEntry.data['hours'] = response.payload['hours']; newEntry.data['mood'] = response.payload['mood']; newEntry.data['comments'] = response.payload['comments']; _entries.removeAt(entryIndex); _entries.add(newEntry); notifyListeners(); // _entries.add(entry); // sortByDate(_entries); } }); } int total() { String dateISO = DateTime.now().toIso8601String(); var referenceDate = DateTime.parse("2023-01-01"); final date = DateTime.parse(dateISO); return date.difference(referenceDate).inDays + 1; } getAll() async { String paginationQuery = Query.offset(0); int max = total(); while (_entries.length < max) { int remainder = max - _entries.length; int limit = remainder > 100 ? 100 : remainder; if (_entries.isNotEmpty) { String lastDate = _entries.last.$id; paginationQuery = Query.cursorAfter(lastDate); } List newEntries = await getEntries( limit: limit, paginationQuery: paginationQuery, ); _entries.addAll(newEntries); notifyListeners(); } _ready = true; } getOne({required String date}) async { try { // print(date); // print(_entries.last.$id); return _entries.singleWhere((element) => element.$id == date); } catch (e) { int offset = DateTime.parse(date).difference(DateTime.parse("2023-01-01")).inDays + 1; List response = await getEntries( limit: 1, paginationQuery: Query.offset(offset), ); _entries.add(response.first); notifyListeners(); } } getEntries({int limit = 100, paginationQuery}) async { var response = await databases.listDocuments( databaseId: APPWRITE_DATABASE_ID, collectionId: COLLECTION, queries: [ Query.orderAsc("date"), paginationQuery, Query.limit(limit), ]); return response.documents; } Future updateEntry( {String? dateISO, List? hours, int? mood, String? comments}) async { String date = formatter.format(DateTime.parse(dateISO!)); int entryIndex = _entries.indexWhere((element) => elDate(element) == date); hours ??= _entries[entryIndex].data['hours']; comments ??= _entries[entryIndex].data['comments']; mood ??= _entries[entryIndex].data['mood']; Document newEntry = await databases.updateDocument( databaseId: APPWRITE_DATABASE_ID, collectionId: COLLECTION, documentId: date, data: {'hours': hours, 'mood': mood, 'comments': comments}, ); print("Updated $date."); _entries.removeAt(entryIndex); _entries.add(newEntry); notifyListeners(); return newEntry; } updateHours(dayEntry, index, value) { List hours = dayEntry.data['hours']; try { hours[index] = num.parse(value); } catch (e) { if (hours.length == index) { hours.add(num.parse(value)); } else { hours.addAll(List.generate(index - hours.length, (i) => -1)); hours.add(num.parse(value)); } } updateEntry(dateISO: dayEntry.data['date'], hours: hours); } Future addEntry( {required String date, List hours = const [], int mood = -1, String comments = ""}) { return databases.createDocument( databaseId: APPWRITE_DATABASE_ID, collectionId: COLLECTION, documentId: date, data: { 'date': DateTime.parse(date), 'hours': hours, 'mood': mood, 'comments': comments }); } Future deleteEntry({required String date}) { return databases.deleteDocument( databaseId: APPWRITE_DATABASE_ID, collectionId: COLLECTION, documentId: date); } }