From 85d3bded283e7d89700b4199dd2366695a488f4f Mon Sep 17 00:00:00 2001 From: vanhalenar Date: Sun, 17 Dec 2023 18:43:24 +0100 Subject: [PATCH 01/11] added calendar task loading from file --- lib/controller/calendar_controller.dart | 47 ++++++++- lib/controller/collection_controller.dart | 32 ------- lib/homepage.dart | 110 ---------------------- lib/view/calendar.dart | 12 +-- 4 files changed, 50 insertions(+), 151 deletions(-) delete mode 100644 lib/controller/collection_controller.dart delete mode 100644 lib/homepage.dart diff --git a/lib/controller/calendar_controller.dart b/lib/controller/calendar_controller.dart index fca8f13..ef251d1 100644 --- a/lib/controller/calendar_controller.dart +++ b/lib/controller/calendar_controller.dart @@ -1,5 +1,7 @@ import 'dart:convert'; +import 'dart:io'; import 'package:flutter/services.dart' show rootBundle; +import 'package:path_provider/path_provider.dart'; import 'package:plantapp/model/task_model.dart'; /// Example event class. @@ -27,8 +29,36 @@ Future> loadTasksFromJson() async { String jsonString = await rootBundle.loadString('assets/tasks.json'); final List parsedJson = json.decode(jsonString); - final List plants = parsedJson.map((eventJson) => Task.fromJson(eventJson)).toList(); - + final List plants = + parsedJson.map((eventJson) => Task.fromJson(eventJson)).toList(); + + List tasks = []; + + for (final plant in plants) { + if (plant.needWater == 1) { + tasks.add(Event("${plant.nickname} | Needs Watering", plant.date)); + } else { + tasks.add(Event("${plant.nickname} | Needs Fertilizing", plant.date)); + } + } + + return tasks; + } catch (e) { + // ignore: avoid_print + print('Error loading tasks from JSON: $e'); + return []; + } +} + +Future> loadTasksFromFile() async { + try { + final file = await _localFile; + String jsonString = await file.readAsString(); + final List parsedJson = json.decode(jsonString); + + final List plants = + parsedJson.map((eventJson) => Task.fromJson(eventJson)).toList(); + List tasks = []; for (final plant in plants) { @@ -47,6 +77,17 @@ Future> loadTasksFromJson() async { } } +Future get _localFile async { + final path = await _localPath; + return File('$path/tasks.json'); +} + +Future get _localPath async { + final directory = await getApplicationDocumentsDirectory(); + + return directory.path; +} + final kToday = DateTime.now(); final kFirstDay = DateTime(kToday.year, kToday.month - 3, kToday.day); -final kLastDay = DateTime(kToday.year, kToday.month + 3, kToday.day); \ No newline at end of file +final kLastDay = DateTime(kToday.year, kToday.month + 3, kToday.day); diff --git a/lib/controller/collection_controller.dart b/lib/controller/collection_controller.dart deleted file mode 100644 index 1a93d4b..0000000 --- a/lib/controller/collection_controller.dart +++ /dev/null @@ -1,32 +0,0 @@ -import 'dart:convert'; -import 'package:flutter/services.dart'; -import 'package:plantapp/model/collection_model.dart'; - -class CollectionController { - List _tasks = []; - - List get tasks => _tasks; - - Future loadPlantsFromAsset() async { - try { - final String data = - await rootBundle.loadString('assets/plantCollection.json'); - final List jsonData = json.decode(data); - _tasks = jsonData.map((e) => Plant.fromJson(e)).toList(); - } catch (e) { - // Handle errors or exceptions - // ignore: avoid_print - print('Error loading data: $e'); - } - } - - String waterOrFertilize(Plant plant) { - if (plant.needWater == 1 && plant.needFertilizer == 0) { - return "water"; - } else if (plant.needFertilizer == 1 && plant.needWater == 0) { - return "fertilize"; - } else { - return "problem"; - } - } -} diff --git a/lib/homepage.dart b/lib/homepage.dart deleted file mode 100644 index 0b7027a..0000000 --- a/lib/homepage.dart +++ /dev/null @@ -1,110 +0,0 @@ -import 'package:flutter/material.dart'; -import 'controller/collection_controller.dart'; -import 'controller/plant_controller.dart'; - -class HomePage extends StatefulWidget { - const HomePage({super.key}); - - @override - State createState() => _HomePageState(); -} - -class _HomePageState extends State { - @override - Widget build(BuildContext context) { - return const Scaffold( - body: PlantCard(), - ); - } -} - -class PlantCard extends StatefulWidget { - const PlantCard({super.key}); - - @override - State createState() => _PlantCardState(); -} - -class _PlantCardState extends State { - var collectionController = CollectionController(); - var plantController = PlantController(); - - Future loadScreen() async { - await collectionController.loadPlantsFromAsset(); - await plantController.loadPlantsFromAsset(); - setState(() {}); - } - - @override - void initState() { - loadScreen(); - super.initState(); - } - - @override - Widget build(BuildContext context) { - return Center( - child: SizedBox( - height: 300, - child: ListView.builder( - scrollDirection: Axis.horizontal, - itemBuilder: (context, index) { - return Card( - margin: const EdgeInsets.all(20), - child: Padding( - padding: const EdgeInsets.all(16), - child: SizedBox( - width: 150, - child: Column( - children: [ - const CircleAvatar( - backgroundImage: - AssetImage('assets/images/monstera.jpg'), - radius: 40, - ), - Align( - alignment: Alignment.centerLeft, - child: Text( - collectionController.tasks[index].nickname, - style: Theme.of(context).textTheme.titleLarge, - maxLines: 1, - overflow: TextOverflow.ellipsis, - ), - ), - Align( - alignment: Alignment.centerLeft, - child: Text( - plantController - .plants[ - collectionController.tasks[index].databaseId - - 1] - .latin, - style: Theme.of(context).textTheme.titleMedium, - ), - ), - Expanded( - child: Align( - alignment: Alignment.bottomCenter, - child: FilledButton.tonal( - onPressed: onpressed, - child: Text( - collectionController.waterOrFertilize( - collectionController.tasks[index]), - style: Theme.of(context).textTheme.labelMedium, - )), - ), - ), - ], - ), - ), - ), - ); - }, - itemCount: collectionController.tasks.length, - ), - ), - ); - } -} - -void onpressed() {} diff --git a/lib/view/calendar.dart b/lib/view/calendar.dart index 3608fdb..339b57b 100644 --- a/lib/view/calendar.dart +++ b/lib/view/calendar.dart @@ -33,7 +33,7 @@ class _CalendarState extends State { } Future loadEvents() async { - List events = await loadTasksFromJson(); + List events = await loadTasksFromFile(); setState(() { _selectedEvents.value = events; }); @@ -47,13 +47,13 @@ class _CalendarState extends State { List _getEventsForDay(DateTime day) { return _selectedEvents.value - .where((event) => isSameDay(event.date, day)) - .toList(); + .where((event) => isSameDay(event.date, day)) + .toList(); } List _getEventsForRange(DateTime start, DateTime end) { List events = []; - + for (DateTime day in daysInRange(start, end)) { events.addAll(_getEventsForDay(day)); } @@ -73,7 +73,7 @@ class _CalendarState extends State { // Load events for the selected day List events = _getEventsForDay(selectedDay); - + if (events.isNotEmpty) { _selectedEvents.value = events; } @@ -165,4 +165,4 @@ class _CalendarState extends State { ), ); } -} \ No newline at end of file +} From 6864fbff97a13fa38e881ef4dd7c4cff1f95cd79 Mon Sep 17 00:00:00 2001 From: Tommikatsu Date: Sun, 17 Dec 2023 21:00:13 +0100 Subject: [PATCH 02/11] Functional user collections --- lib/controller/calendar_controller.dart | 45 +++++++++- lib/controller/usercoll_controller.dart | 8 +- lib/view/calendar.dart | 18 ++-- lib/view/plant_collection.dart | 106 ++++++++++++++++++------ 4 files changed, 134 insertions(+), 43 deletions(-) diff --git a/lib/controller/calendar_controller.dart b/lib/controller/calendar_controller.dart index fca8f13..c824f5e 100644 --- a/lib/controller/calendar_controller.dart +++ b/lib/controller/calendar_controller.dart @@ -1,5 +1,7 @@ import 'dart:convert'; +import 'dart:io'; import 'package:flutter/services.dart' show rootBundle; +import 'package:path_provider/path_provider.dart'; import 'package:plantapp/model/task_model.dart'; /// Example event class. @@ -27,8 +29,36 @@ Future> loadTasksFromJson() async { String jsonString = await rootBundle.loadString('assets/tasks.json'); final List parsedJson = json.decode(jsonString); - final List plants = parsedJson.map((eventJson) => Task.fromJson(eventJson)).toList(); - + final List plants = + parsedJson.map((eventJson) => Task.fromJson(eventJson)).toList(); + + List tasks = []; + + for (final plant in plants) { + if (plant.needWater == 1) { + tasks.add(Event("${plant.nickname} | Needs Watering", plant.date)); + } else { + tasks.add(Event("${plant.nickname} | Needs Fertilizing", plant.date)); + } + } + + return tasks; + } catch (e) { + // ignore: avoid_print + print('Error loading tasks from JSON: $e'); + return []; + } +} + +Future> loadTasksFromFile() async { + try { + final file = await _localFile; + String jsonString = await file.readAsString(); + final List parsedJson = json.decode(jsonString); + + final List plants = + parsedJson.map((eventJson) => Task.fromJson(eventJson)).toList(); + List tasks = []; for (final plant in plants) { @@ -47,6 +77,17 @@ Future> loadTasksFromJson() async { } } +Future get _localFile async { + final path = await _localPath; + return File('$path/tasks.json'); +} + +Future get _localPath async { + final directory = await getApplicationDocumentsDirectory(); + + return directory.path; +} + final kToday = DateTime.now(); final kFirstDay = DateTime(kToday.year, kToday.month - 3, kToday.day); final kLastDay = DateTime(kToday.year, kToday.month + 3, kToday.day); \ No newline at end of file diff --git a/lib/controller/usercoll_controller.dart b/lib/controller/usercoll_controller.dart index 230ca3c..052b8bd 100644 --- a/lib/controller/usercoll_controller.dart +++ b/lib/controller/usercoll_controller.dart @@ -47,10 +47,12 @@ class UserCollController { } } - Future newCollection(UserColl newColl) async { + Future newCollection(String collName) async { await loadCollectionsFromFile(); - _colls.add(newColl); - print("collName: ${newColl.collName}"); + _colls.add(UserColl( + collName: collName, + plantIds: [], + plantNames: [])); await _writeToFile(_colls); } diff --git a/lib/view/calendar.dart b/lib/view/calendar.dart index 3608fdb..f40bc2f 100644 --- a/lib/view/calendar.dart +++ b/lib/view/calendar.dart @@ -21,6 +21,7 @@ class _CalendarState extends State { DateTime? _selectedDay; DateTime? _rangeStart; DateTime? _rangeEnd; + List _events = []; @override void initState() { @@ -33,8 +34,9 @@ class _CalendarState extends State { } Future loadEvents() async { - List events = await loadTasksFromJson(); + List events = await loadTasksFromFile(); setState(() { + _events = events; _selectedEvents.value = events; }); } @@ -46,14 +48,12 @@ class _CalendarState extends State { } List _getEventsForDay(DateTime day) { - return _selectedEvents.value - .where((event) => isSameDay(event.date, day)) - .toList(); + return _events.where((event) => isSameDay(event.date, day)).toList(); } List _getEventsForRange(DateTime start, DateTime end) { List events = []; - + for (DateTime day in daysInRange(start, end)) { events.addAll(_getEventsForDay(day)); } @@ -72,11 +72,7 @@ class _CalendarState extends State { }); // Load events for the selected day - List events = _getEventsForDay(selectedDay); - - if (events.isNotEmpty) { - _selectedEvents.value = events; - } + _selectedEvents.value = _getEventsForDay(selectedDay); } } @@ -153,7 +149,7 @@ class _CalendarState extends State { borderRadius: BorderRadius.circular(12.0), ), child: ListTile( - title: Text('${value[index]}'), + title: Text('${value[index].title}'), ), ); }, diff --git a/lib/view/plant_collection.dart b/lib/view/plant_collection.dart index 1684188..d485a04 100644 --- a/lib/view/plant_collection.dart +++ b/lib/view/plant_collection.dart @@ -81,6 +81,48 @@ class _PlantInstState extends State { ); } + Future _dialogNewCollection(BuildContext context) { + return showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text('New Collection'), + content: TextField( + controller: usercollsController, + decoration: InputDecoration( + hintText: 'Name', + hintStyle: TextStyle(color: Colors.grey), + contentPadding: + EdgeInsets.symmetric(vertical: 10.0, horizontal: 10.0), + border: OutlineInputBorder(), + ), + ), + actions: [ + TextButton( + style: TextButton.styleFrom( + textStyle: Theme.of(context).textTheme.labelLarge, + ), + child: const Text('Create'), + onPressed: () async { + await collCont.newCollection(usercollsController.text); + Navigator.of(context).pop(); + }, + ), + TextButton( + style: TextButton.styleFrom( + textStyle: Theme.of(context).textTheme.labelLarge, + ), + child: const Text('Cancel'), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ], + ); + }, + ); + } + Future _dialogChangeName(BuildContext context) { return showDialog( context: context, @@ -88,15 +130,15 @@ class _PlantInstState extends State { return AlertDialog( title: const Text('Rename Collection'), content: TextField( - controller: usercollsController, - decoration: InputDecoration( - hintText: 'New Name', - hintStyle: TextStyle(color: Colors.grey), - contentPadding: - EdgeInsets.symmetric(vertical: 10.0, horizontal: 10.0), - border: OutlineInputBorder(), - ), - ), + controller: usercollsController, + decoration: InputDecoration( + hintText: 'New Name', + hintStyle: TextStyle(color: Colors.grey), + contentPadding: + EdgeInsets.symmetric(vertical: 10.0, horizontal: 10.0), + border: OutlineInputBorder(), + ), + ), actions: [ TextButton( style: TextButton.styleFrom( @@ -160,20 +202,20 @@ class _PlantInstState extends State { context: context, builder: (BuildContext context) { return AlertDialog( - title: const Text('Add Plant'), - content: Expanded( - child: ListView.builder( - itemCount: collCont.colls[0].plantIds.length, - itemBuilder: (context, index) { - return ElevatedButton( + content: Container( + height: 200, // Set a specific height + child: Column( + children: List.generate( + collCont.colls[0].plantIds.length, + (index) => ElevatedButton( onPressed: () async { await collCont.addPlantToCollection(index, selectedCollectionIndex); Navigator.of(context).pop(); }, - child: Text('${collCont.colls[index].plantIds}'), - ); - }, + child: Text('${collCont.colls[selectedCollectionIndex].plantNames[index]}'), + ), + ), ), ), actions: [ @@ -198,18 +240,19 @@ class _PlantInstState extends State { builder: (BuildContext context) { return AlertDialog( title: const Text('Remove Plant'), - content: Expanded( - child: ListView.builder( - itemCount: collCont.colls[selectedCollectionIndex].plantIds.length, - itemBuilder: (context, index) { - return ElevatedButton( + content: Container( + height: 200, // Set a specific height + child: Column( + children: List.generate( + collCont.colls[selectedCollectionIndex].plantIds.length, + (index) => ElevatedButton( onPressed: () async { await collCont.removePlantFromCollection(index, selectedCollectionIndex); Navigator.of(context).pop(); }, - child: Text('${collCont.colls[index].plantIds}'), - ); - }, + child: Text('${collCont.colls[selectedCollectionIndex].plantNames[index]}'), + ), + ), ), ), actions: [ @@ -231,7 +274,16 @@ class _PlantInstState extends State { @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar(title: const Text("User's Collections")), + appBar: AppBar(title: Row( + children: [ + Text("User's Collections"), + Spacer(), + GestureDetector( + onTap: () => _dialogNewCollection(context), + child: Icon(Icons.add, size: 40.0) + ), + ] + )), body: ListView.builder( itemCount: collCont.colls.length, itemBuilder: (context, index) => ListTile( From 24179a45218cf80a2431cdb3fb48641e78dcb3ee Mon Sep 17 00:00:00 2001 From: Tommikatsu Date: Sun, 17 Dec 2023 21:48:43 +0100 Subject: [PATCH 03/11] Fixed user collections --- lib/controller/usercoll_controller.dart | 13 +++++++------ lib/view/plant_collection.dart | 2 +- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/lib/controller/usercoll_controller.dart b/lib/controller/usercoll_controller.dart index 052b8bd..55d3745 100644 --- a/lib/controller/usercoll_controller.dart +++ b/lib/controller/usercoll_controller.dart @@ -1,3 +1,10 @@ +/* + Author: Tomáš Mikát + Description: Controller for page for user's collections +*/ + +// ignore_for_file: prefer_const_constructors, avoid_print, prefer_const_literals_to_create_immutables + import 'dart:convert'; import 'dart:io'; import 'package:flutter/services.dart'; @@ -15,7 +22,6 @@ class UserCollController { final List jsonData = json.decode(data); _colls = jsonData.map((e) => UserColl.fromJson(e)).toList(); } catch (e) { - // ignore: avoid_print print('Error loading data: $e'); } } @@ -90,11 +96,6 @@ class UserCollController { await _writeToFile(_colls); } - Future getCollection(int collName) async { - await loadCollectionsFromFile(); - return _colls.firstWhere((coll) => coll.collName == collName); - } - void seedFile() async { await loadCollectionsFromAsset(); _writeToFile(_colls); diff --git a/lib/view/plant_collection.dart b/lib/view/plant_collection.dart index d485a04..f15dada 100644 --- a/lib/view/plant_collection.dart +++ b/lib/view/plant_collection.dart @@ -213,7 +213,7 @@ class _PlantInstState extends State { await collCont.addPlantToCollection(index, selectedCollectionIndex); Navigator.of(context).pop(); }, - child: Text('${collCont.colls[selectedCollectionIndex].plantNames[index]}'), + child: Text('${collCont.colls[0].plantNames[index]}'), ), ), ), From 70ef29d1f098e4da8d67fd0b2cb9332f676d9026 Mon Sep 17 00:00:00 2001 From: kapolious Date: Sun, 17 Dec 2023 22:28:58 +0100 Subject: [PATCH 04/11] renamed default to My Plants --- assets/userCollections.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/userCollections.json b/assets/userCollections.json index d7953f2..9541e19 100644 --- a/assets/userCollections.json +++ b/assets/userCollections.json @@ -1,6 +1,6 @@ [ { - "collName" : "_DEFAULT_", + "collName" : "My Plants", "plantIds" : [1], "plantNames" : ["Sal"] }, From 0869ce21dc6b44b2be3118ed931c1fe25bfdfc12 Mon Sep 17 00:00:00 2001 From: vanhalenar Date: Sun, 17 Dec 2023 22:37:54 +0100 Subject: [PATCH 05/11] added seedIfNoFileExists() functions --- assets/tasks.json | 15 +-- lib/controller/coll_controller.dart | 123 ++++++++++++++---------- lib/controller/usercoll_controller.dart | 26 ++++- lib/main.dart | 7 +- lib/model/task_model.dart | 10 +- lib/view/achievements.dart | 10 +- 6 files changed, 119 insertions(+), 72 deletions(-) diff --git a/assets/tasks.json b/assets/tasks.json index f7ffca7..358dadb 100644 --- a/assets/tasks.json +++ b/assets/tasks.json @@ -3,39 +3,34 @@ "databaseId" : 1, "nickname" : "Sal", "needWater" : 1, - "needFertilizer" : 0, - "date" : "2023-12-17" + "needFertilizer" : 0 }, { "databaseId" : 6, "nickname" : "Joey", "needWater" : 1, - "needFertilizer": 0, - "date" : "2023-12-17" + "needFertilizer": 0 }, { "databaseId" : 7, "nickname" : "Eldrani, the Chosen One", "needWater" : 0, - "needFertilizer": 1, - "date" : "2023-12-17" + "needFertilizer": 1 }, { "databaseId" : 8, "nickname" : "Jenny", "needWater" : 1, - "needFertilizer": 0, - "date" : "2023-12-17" + "needFertilizer": 0 }, { "databaseId" : 8, "nickname" : "Jenny", "needWater" : 0, - "needFertilizer": 1, - "date" : "2023-12-17" + "needFertilizer": 1 } ] \ No newline at end of file diff --git a/lib/controller/coll_controller.dart b/lib/controller/coll_controller.dart index a3c67e3..3788e59 100644 --- a/lib/controller/coll_controller.dart +++ b/lib/controller/coll_controller.dart @@ -17,7 +17,6 @@ import 'package:plantapp/model/task_model.dart'; import 'task_controller.dart'; import 'plant_controller.dart'; - class CollController { List _collection = []; @@ -35,61 +34,61 @@ class CollController { } Future savePlant(Collection newPlant) async { - await loadPlantsFromFile(); - _collection.add(newPlant); - print("databaseId: ${newPlant.databaseId}"); + await loadPlantsFromFile(); + _collection.add(newPlant); + print("databaseId: ${newPlant.databaseId}"); - Directory appDocumentsDirectory = await getApplicationDocumentsDirectory(); - String imageDirectory = "${appDocumentsDirectory.path}/images"; + Directory appDocumentsDirectory = await getApplicationDocumentsDirectory(); + String imageDirectory = "${appDocumentsDirectory.path}/images"; - // Create the directory if it doesn't exist - await Directory(imageDirectory).create(recursive: true); + // Create the directory if it doesn't exist + await Directory(imageDirectory).create(recursive: true); - String imagePath = "$imageDirectory/${newPlant.databaseId}.jpg"; + String imagePath = "$imageDirectory/${newPlant.databaseId}.jpg"; - // Save the image file - if (newPlant.imageFile != null) { - // Save the image file to the specified path - await newPlant.imageFile!.copy(imagePath); - newPlant.photo = imagePath; - } + // Save the image file + if (newPlant.imageFile != null) { + // Save the image file to the specified path + await newPlant.imageFile!.copy(imagePath); + newPlant.photo = imagePath; + } - await _writeToFile(_collection); - - TaskController taskController = TaskController(); - await taskController.loadTasksFromFile(); - - PlantController plantController = PlantController(); - await plantController.loadPlantsFromAsset(); - int waterInterval = - plantController.plants[newPlant.databaseId - 1].wateringPeriod; - int fertilizeInterval = - plantController.plants[newPlant.databaseId - 1].fertilizingPeriod; - - DateTime waterDate = - newPlant.lastWatered.add(Duration(days: waterInterval)); - DateTime fertilizeDate = - newPlant.lastFertilized.add(Duration(days: fertilizeInterval)); - - Task waterTask = Task( - databaseId: newPlant.databaseId, - nickname: newPlant.nickname, - needWater: 1, - needFertilizer: 0, - date: waterDate); - - Task fertilizeTask = Task( - databaseId: newPlant.databaseId, - nickname: newPlant.nickname, - needWater: 0, - needFertilizer: 1, - date: fertilizeDate); - - taskController.tasks.add(waterTask); - taskController.tasks.add(fertilizeTask); - String encoded = jsonEncode(taskController.tasks); - taskController.writeTasks(encoded); -} + await _writeToFile(_collection); + + TaskController taskController = TaskController(); + await taskController.loadTasksFromFile(); + + PlantController plantController = PlantController(); + await plantController.loadPlantsFromAsset(); + int waterInterval = + plantController.plants[newPlant.databaseId - 1].wateringPeriod; + int fertilizeInterval = + plantController.plants[newPlant.databaseId - 1].fertilizingPeriod; + + DateTime waterDate = + newPlant.lastWatered.add(Duration(days: waterInterval)); + DateTime fertilizeDate = + newPlant.lastFertilized.add(Duration(days: fertilizeInterval)); + + Task waterTask = Task( + databaseId: newPlant.databaseId, + nickname: newPlant.nickname, + needWater: 1, + needFertilizer: 0, + date: waterDate); + + Task fertilizeTask = Task( + databaseId: newPlant.databaseId, + nickname: newPlant.nickname, + needWater: 0, + needFertilizer: 1, + date: fertilizeDate); + + taskController.tasks.add(waterTask); + taskController.tasks.add(fertilizeTask); + String encoded = jsonEncode(taskController.tasks); + taskController.writeTasks(encoded); + } Future _writeToFile(List plants) async { try { @@ -151,6 +150,28 @@ class CollController { _writeToFile(_collection); } + Future get _localPath async { + final directory = await getApplicationDocumentsDirectory(); + + return directory.path; + } + + Future get _localFile async { + final path = await _localPath; + return File('$path/plantColl.json'); + } + + void seedIfNoFileExists() async { + final file = await _localFile; + bool fileExists = await file.exists(); + if (fileExists) { + print('file do be existin doe'); + } else { + print('file aint there brudda'); + seedFile(); + } + } + int calculateDaysUntilNextAction(DateTime lastDate, int period) { // Calculate the next watering date DateTime nextDate = lastDate.add(Duration(days: period)); diff --git a/lib/controller/usercoll_controller.dart b/lib/controller/usercoll_controller.dart index 230ca3c..a0ef276 100644 --- a/lib/controller/usercoll_controller.dart +++ b/lib/controller/usercoll_controller.dart @@ -11,7 +11,8 @@ class UserCollController { Future loadCollectionsFromAsset() async { try { - final String data = await rootBundle.loadString('assets/userCollections.json'); + final String data = + await rootBundle.loadString('assets/userCollections.json'); final List jsonData = json.decode(data); _colls = jsonData.map((e) => UserColl.fromJson(e)).toList(); } catch (e) { @@ -98,4 +99,25 @@ class UserCollController { _writeToFile(_colls); } -} \ No newline at end of file + Future get _localPath async { + final directory = await getApplicationDocumentsDirectory(); + + return directory.path; + } + + Future get _localFile async { + final path = await _localPath; + return File('$path/userCollections.json'); + } + + void seedIfNoFileExists() async { + final file = await _localFile; + bool fileExists = await file.exists(); + if (fileExists) { + print('file do be existin doe'); + } else { + print('file aint there brudda'); + seedFile(); + } + } +} diff --git a/lib/main.dart b/lib/main.dart index 601338b..c48e93e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -10,7 +10,6 @@ import 'controller/coll_controller.dart'; import 'controller/usercoll_controller.dart'; import 'controller/achievements_controller.dart'; - void main() { runApp(const MyApp()); //seeders, remove when deploying @@ -18,10 +17,16 @@ void main() { var collController = CollController(); var usercollController = UserCollController(); var achController = AchievementsController(); + taskController.seedFile(); collController.seedFile(); usercollController.seedFile(); achController.seedFile(); + + /*taskController.seedIfNoFileExists(); + collController.seedIfNoFileExists(); + usercollController.seedIfNoFileExists(); + achController.seedIfNoFileExists();*/ } class MyApp extends StatelessWidget { diff --git a/lib/model/task_model.dart b/lib/model/task_model.dart index 6efb163..65013f1 100644 --- a/lib/model/task_model.dart +++ b/lib/model/task_model.dart @@ -18,7 +18,15 @@ class Task { nickname: json["nickname"], needWater: json["needWater"], needFertilizer: json["needFertilizer"], - date: DateTime.parse(json["date"])); + date: returnDate(json)); + } + + static DateTime returnDate(Map json) { + if (json.containsKey("date")) { + return DateTime.parse(json["date"]); + } else { + return DateTime.now(); + } } Map toJson() => { diff --git a/lib/view/achievements.dart b/lib/view/achievements.dart index ab4ff6f..197eb5a 100644 --- a/lib/view/achievements.dart +++ b/lib/view/achievements.dart @@ -197,27 +197,23 @@ class LineProgOrNot extends StatefulWidget { final Achievement achievement; @override - State createState() => _LineProgOrNotState(achievement); + State createState() => _LineProgOrNotState(); } class _LineProgOrNotState extends State with TickerProviderStateMixin { - _LineProgOrNotState(this.achievement); - late AnimationController controller; - final Achievement achievement; + //Achievement achievement; @override void initState() { controller = AnimationController( - /// [AnimationController]s can be created with `vsync: this` because of - /// [TickerProviderStateMixin]. vsync: this, duration: const Duration(seconds: 1), )..addListener(() { setState(() {}); }); - controller.animateTo(achievement.current / achievement.max); + controller.animateTo(widget.achievement.current / widget.achievement.max); super.initState(); } From 49cbe34d382cb24b6b7abbac9e1ee7d8c32ab20b Mon Sep 17 00:00:00 2001 From: vanhalenar Date: Sun, 17 Dec 2023 22:48:16 +0100 Subject: [PATCH 06/11] new plants are added to default user collection now --- lib/controller/coll_controller.dart | 6 ++++++ lib/controller/usercoll_controller.dart | 13 +++++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/lib/controller/coll_controller.dart b/lib/controller/coll_controller.dart index 3788e59..5ca265d 100644 --- a/lib/controller/coll_controller.dart +++ b/lib/controller/coll_controller.dart @@ -16,6 +16,7 @@ import 'package:plantapp/model/coll_model.dart'; import 'package:plantapp/model/task_model.dart'; import 'task_controller.dart'; import 'plant_controller.dart'; +import 'usercoll_controller.dart'; class CollController { List _collection = []; @@ -88,6 +89,11 @@ class CollController { taskController.tasks.add(fertilizeTask); String encoded = jsonEncode(taskController.tasks); taskController.writeTasks(encoded); + + UserCollController userCollController = UserCollController(); + await userCollController.loadCollectionsFromFile(); + + userCollController.addPlantToCollectionByPlant(newPlant); } Future _writeToFile(List plants) async { diff --git a/lib/controller/usercoll_controller.dart b/lib/controller/usercoll_controller.dart index 69f9e5e..1c944a9 100644 --- a/lib/controller/usercoll_controller.dart +++ b/lib/controller/usercoll_controller.dart @@ -10,6 +10,7 @@ import 'dart:io'; import 'package:flutter/services.dart'; import 'package:path_provider/path_provider.dart'; import 'package:plantapp/model/usercoll_model.dart'; +import 'package:plantapp/model/coll_model.dart'; class UserCollController { List _colls = []; @@ -56,10 +57,7 @@ class UserCollController { Future newCollection(String collName) async { await loadCollectionsFromFile(); - _colls.add(UserColl( - collName: collName, - plantIds: [], - plantNames: [])); + _colls.add(UserColl(collName: collName, plantIds: [], plantNames: [])); await _writeToFile(_colls); } @@ -88,6 +86,13 @@ class UserCollController { await _writeToFile(_colls); } + Future addPlantToCollectionByPlant(Collection plant) async { + await loadCollectionsFromFile(); + _colls[0].plantIds.add(plant.databaseId); + _colls[0].plantNames.add(plant.nickname); + await _writeToFile(_colls); + } + Future removePlantFromCollection(int plantIndex, int collIndex) async { await loadCollectionsFromFile(); _colls[0].plantIds.add(_colls[collIndex].plantIds[plantIndex]); From c4d4d47b12a2e0cde0c8b689a829f6ad4bc31761 Mon Sep 17 00:00:00 2001 From: vanhalenar Date: Sun, 17 Dec 2023 23:02:48 +0100 Subject: [PATCH 07/11] Added README.md --- README.md | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 5f795fd..73d34ff 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,19 @@ # plantapp -VUT FIT - ITU project: plant care \ No newline at end of file +VUT FIT - ITU project: plant care + +## Inštalácia + +1. Stiahnite si aplikáciu (.apk) zo zdieľaného priečinka: https://drive.google.com/drive/folders/1sQ4Ks0TKdQL-SqnuJswaQkFLdi0TJEVA?usp=sharing + +2. Presuňte aplikáciu do android telefónu + +3. V telefóne nájdite a spustite .apk súbor + +## Závislosti + +cupertino_icons: https://pub.dev/packages/cupertino_icons/license +google_fonts: https://fonts.google.com/ (Free, Open Source Software) +path_provider: https://pub.dev/packages/path_provider/license +table_calendar: https://pub.dev/packages/table_calendar/license +image_picker: https://pub.dev/packages/image_picker/license \ No newline at end of file From 3eae44493f9d284f7420677e3cdd22496b6c81f4 Mon Sep 17 00:00:00 2001 From: vanhalenar Date: Sun, 17 Dec 2023 23:03:51 +0100 Subject: [PATCH 08/11] Modified readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 73d34ff..c6527c0 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ VUT FIT - ITU project: plant care 2. Presuňte aplikáciu do android telefónu -3. V telefóne nájdite a spustite .apk súbor +3. V telefóne nájdite a spustite .apk súbor, aplikácia sa nainštaluje ## Závislosti From 9a1d1fac0e5d56d0aa728a7a3376f2288137a8de Mon Sep 17 00:00:00 2001 From: kapolious Date: Sun, 17 Dec 2023 23:13:20 +0100 Subject: [PATCH 09/11] working on viewing --- lib/view/plant_collection.dart | 166 +++++++++++++++++++-------------- 1 file changed, 95 insertions(+), 71 deletions(-) diff --git a/lib/view/plant_collection.dart b/lib/view/plant_collection.dart index f15dada..5f222df 100644 --- a/lib/view/plant_collection.dart +++ b/lib/view/plant_collection.dart @@ -2,18 +2,20 @@ import 'package:flutter/material.dart'; import 'package:plantapp/model/plant_model.dart'; -import 'package:plantapp/model/usercoll_model.dart'; +import 'package:plantapp/model/coll_model.dart'; +import 'package:plantapp/controller/coll_controller.dart'; import 'package:plantapp/controller/plant_controller.dart'; import 'package:plantapp/controller/usercoll_controller.dart'; +import 'package:plantapp/view/plant_added.dart'; class PlantCollection extends StatefulWidget { const PlantCollection({Key? key}) : super(key: key); @override - State createState() => _PlantCollectionState(); + State createState() => PlantCollectionState(); } -class _PlantCollectionState extends State { +class PlantCollectionState extends State { @override Widget build(BuildContext context) { return const Scaffold(body: PlantInst()); @@ -21,7 +23,16 @@ class _PlantCollectionState extends State { } class PlantInst extends StatefulWidget { - const PlantInst({Key? key}) : super(key: key); + final Plant plantType; + final CollController collectionController; + final Collection plant; + + const PlantInst({ + required this.plantType, + required this.collectionController, + required this.plant, + Key? key, + }) : super(key: key); @override State createState() => _PlantInstState(); @@ -305,73 +316,86 @@ class _PlantInstState extends State { Icon(Icons.settings), ],), ), - subtitle: _contentGridView(index)))); + subtitle: contentGridView(index)))); } - Widget _contentGridView(int cindex) { - return GridView.builder( - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 2, childAspectRatio: 0.67), - itemCount: collCont.colls[cindex].plantIds.length, - itemBuilder: (context, index) { - return Card( - //color: Colors.green[300], - child: Padding( - padding: const EdgeInsets.all(10), - child: SizedBox( - width: 140, - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - mainAxisSize: MainAxisSize.min, - children: [ - ClipRRect( - borderRadius: BorderRadius.circular(10), - child: Container( - alignment: Alignment.center, - child: const Image( - image: AssetImage( - 'assets/images/monstera.jpg'), - height: 140, - width: 140, - fit: BoxFit.fitWidth, - ))), - const SizedBox(height: 9), - Expanded( - child: Align( - alignment: Alignment.topLeft, - child: Text( - collCont.colls[cindex].plantNames[index], - textAlign: TextAlign.start, - style: const TextStyle( - fontSize: 26, - fontWeight: FontWeight.w600, - height: 1, - leadingDistribution: - TextLeadingDistribution.even), - ), - ), - ), - Align( - alignment: Alignment.topLeft, - child: Text( - overflow: TextOverflow.ellipsis, - plantCont - .plants[ - collCont.colls[cindex].plantIds[index] - - 1] - .latin, - style: const TextStyle( - fontSize: 18, - fontWeight: FontWeight.w400, - color: Colors.black54, - height: 1.0, - leadingDistribution: - TextLeadingDistribution.even), - ), - ) - ])))); - }); - } +Widget contentGridView(int cindex) { + return GridView.builder( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, + childAspectRatio: 0.67, + ), + itemCount: collCont.colls[cindex].plantIds.length, + itemBuilder: (context, index) { + return GestureDetector( + onTap: () { + Navigator.push(context, MaterialPageRoute(builder: (context) => PlantAdded(plant: widget.plant, collController: widget.collectionController, plantType: widget.plantType)),); + }, + child: Card( + //color: Colors.green[300], + child: Padding( + padding: const EdgeInsets.all(10), + child: SizedBox( + width: 140, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + mainAxisSize: MainAxisSize.min, + children: [ + ClipRRect( + borderRadius: BorderRadius.circular(10), + child: Container( + alignment: Alignment.center, + child: const Image( + image: AssetImage('assets/images/monstera.jpg'), + height: 140, + width: 140, + fit: BoxFit.fitWidth, + ), + ), + ), + const SizedBox(height: 9), + Expanded( + child: Align( + alignment: Alignment.topLeft, + child: Text( + collCont.colls[cindex].plantNames[index], + textAlign: TextAlign.start, + style: const TextStyle( + fontSize: 26, + fontWeight: FontWeight.w600, + height: 1, + leadingDistribution: TextLeadingDistribution.even, + ), + ), + ), + ), + Align( + alignment: Alignment.topLeft, + child: Text( + overflow: TextOverflow.ellipsis, + plantCont + .plants[collCont.colls[cindex].plantIds[index] - 1] + .latin, + style: const TextStyle( + fontSize: 18, + fontWeight: FontWeight.w400, + color: Colors.black54, + height: 1.0, + leadingDistribution: TextLeadingDistribution.even, + ), + ), + ) + ], + ), + ), + ), + ), + ); + }, + ); } + +} + From abc218d47261ee5edf142b443bdb0d15d6e33298 Mon Sep 17 00:00:00 2001 From: vanhalenar Date: Sun, 17 Dec 2023 23:21:37 +0100 Subject: [PATCH 10/11] Added headers --- lib/controller/achievements_controller.dart | 5 ++++ lib/controller/coll_controller.dart | 3 +++ lib/controller/task_controller.dart | 5 ++++ lib/controller/usercoll_controller.dart | 3 +++ lib/main.dart | 6 +++++ lib/model/achievement_model.dart | 5 ++++ lib/model/collection_model.dart | 27 --------------------- lib/model/task_model.dart | 5 ++++ lib/view/achievements.dart | 5 ++++ lib/view/homepage.dart | 5 ++++ 10 files changed, 42 insertions(+), 27 deletions(-) delete mode 100644 lib/model/collection_model.dart diff --git a/lib/controller/achievements_controller.dart b/lib/controller/achievements_controller.dart index f429a49..211150b 100644 --- a/lib/controller/achievements_controller.dart +++ b/lib/controller/achievements_controller.dart @@ -1,3 +1,8 @@ +/* + Author: Timotej Halenár + Description: Used to retrieve, modify and store achievement data +*/ + // ignore_for_file: avoid_print import 'dart:io'; diff --git a/lib/controller/coll_controller.dart b/lib/controller/coll_controller.dart index 5ca265d..bff79a9 100644 --- a/lib/controller/coll_controller.dart +++ b/lib/controller/coll_controller.dart @@ -4,6 +4,9 @@ It includes methods for loading plant data from an asset, saving new plants, updating existing plants, retrieving a specific plant, deleting a plant, and performing calculations related to plant actions. The class uses the PlantController and TaskController classes for additional functionality. + + Co-Author: Timotej Halenár + Contribution: Added task scheduling functionality. */ // ignore_for_file: avoid_print diff --git a/lib/controller/task_controller.dart b/lib/controller/task_controller.dart index d313481..26d4105 100644 --- a/lib/controller/task_controller.dart +++ b/lib/controller/task_controller.dart @@ -1,3 +1,8 @@ +/* + Author: Timotej Halenár + Description: Used to retrieve, modify and store task data, + provides converter functions +*/ // ignore_for_file: avoid_print, curly_braces_in_flow_control_structures import 'dart:convert'; diff --git a/lib/controller/usercoll_controller.dart b/lib/controller/usercoll_controller.dart index 1c944a9..c373ad4 100644 --- a/lib/controller/usercoll_controller.dart +++ b/lib/controller/usercoll_controller.dart @@ -1,6 +1,9 @@ /* Author: Tomáš Mikát Description: Controller for page for user's collections + + Co-Author: Timotej Halenár + Contribution: addPlantToCollectionByPlant() method. */ // ignore_for_file: prefer_const_constructors, avoid_print, prefer_const_literals_to_create_immutables diff --git a/lib/main.dart b/lib/main.dart index c48e93e..6d899b2 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,3 +1,9 @@ +/* + Author: Timotej Halenár + Description: Main file. Renders bottom navigation bar and provides + navigation to all other pages. Contains theme definition. Contains + seeding function calls. +*/ import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'view/homepage.dart'; diff --git a/lib/model/achievement_model.dart b/lib/model/achievement_model.dart index 799f779..393d9ad 100644 --- a/lib/model/achievement_model.dart +++ b/lib/model/achievement_model.dart @@ -1,3 +1,8 @@ +/* + Author: Timotej Halenár + Description: Represents an achievement, provides factory to create + achievements from JSON and encode data as JSON +*/ class Achievement { int databaseId; String nickname; diff --git a/lib/model/collection_model.dart b/lib/model/collection_model.dart deleted file mode 100644 index f1eb8d5..0000000 --- a/lib/model/collection_model.dart +++ /dev/null @@ -1,27 +0,0 @@ -class Plant { - int databaseId; - String nickname; - int needWater; - int needFertilizer; - - Plant( - {required this.databaseId, - required this.nickname, - required this.needWater, - required this.needFertilizer}); - - factory Plant.fromJson(Map json) { - return Plant( - databaseId: json["databaseId"], - nickname: json["nickname"], - needWater: json["needWater"], - needFertilizer: json["needFertilizer"]); - } - - Map toJson() => { - 'databaseId': databaseId, - 'nickname': nickname, - 'needWater': needWater, - 'needFertilizer': needFertilizer - }; -} diff --git a/lib/model/task_model.dart b/lib/model/task_model.dart index 65013f1..e81be14 100644 --- a/lib/model/task_model.dart +++ b/lib/model/task_model.dart @@ -1,3 +1,8 @@ +/* + Author: Timotej Halenár + Description: Represents a task, provides factory to create + tasks from JSON and encode data as JSON +*/ class Task { int databaseId; String nickname; diff --git a/lib/view/achievements.dart b/lib/view/achievements.dart index 197eb5a..c2888fb 100644 --- a/lib/view/achievements.dart +++ b/lib/view/achievements.dart @@ -1,3 +1,8 @@ +/* + Author: Timotej Halenár + Description: Achievements View. Renders incomplete and completed + achievements +*/ // ignore_for_file: prefer_const_constructors import 'package:flutter/material.dart'; diff --git a/lib/view/homepage.dart b/lib/view/homepage.dart index a3450de..1e31cfe 100644 --- a/lib/view/homepage.dart +++ b/lib/view/homepage.dart @@ -1,3 +1,8 @@ +/* + Author: Timotej Halenár + Description: Homepage View. Renders tasks, provides functionality + to mark task as finished, renders incomplete achievements +*/ import 'package:flutter/material.dart'; import 'package:plantapp/controller/task_controller.dart'; import 'package:plantapp/controller/achievements_controller.dart'; From 010e29675f9f2d7b8dd0b3fc2661a73d6d297bae Mon Sep 17 00:00:00 2001 From: kapolious Date: Sun, 17 Dec 2023 23:41:52 +0100 Subject: [PATCH 11/11] reverted changes --- lib/view/plant_collection.dart | 168 ++++++++++++++------------------- 1 file changed, 72 insertions(+), 96 deletions(-) diff --git a/lib/view/plant_collection.dart b/lib/view/plant_collection.dart index 5f222df..3900031 100644 --- a/lib/view/plant_collection.dart +++ b/lib/view/plant_collection.dart @@ -2,20 +2,18 @@ import 'package:flutter/material.dart'; import 'package:plantapp/model/plant_model.dart'; -import 'package:plantapp/model/coll_model.dart'; -import 'package:plantapp/controller/coll_controller.dart'; +import 'package:plantapp/model/usercoll_model.dart'; import 'package:plantapp/controller/plant_controller.dart'; import 'package:plantapp/controller/usercoll_controller.dart'; -import 'package:plantapp/view/plant_added.dart'; class PlantCollection extends StatefulWidget { const PlantCollection({Key? key}) : super(key: key); @override - State createState() => PlantCollectionState(); + State createState() => _PlantCollectionState(); } -class PlantCollectionState extends State { +class _PlantCollectionState extends State { @override Widget build(BuildContext context) { return const Scaffold(body: PlantInst()); @@ -23,16 +21,7 @@ class PlantCollectionState extends State { } class PlantInst extends StatefulWidget { - final Plant plantType; - final CollController collectionController; - final Collection plant; - - const PlantInst({ - required this.plantType, - required this.collectionController, - required this.plant, - Key? key, - }) : super(key: key); + const PlantInst({Key? key}) : super(key: key); @override State createState() => _PlantInstState(); @@ -316,86 +305,73 @@ class _PlantInstState extends State { Icon(Icons.settings), ],), ), - subtitle: contentGridView(index)))); + subtitle: _contentGridView(index)))); } -Widget contentGridView(int cindex) { - return GridView.builder( - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 2, - childAspectRatio: 0.67, - ), - itemCount: collCont.colls[cindex].plantIds.length, - itemBuilder: (context, index) { - return GestureDetector( - onTap: () { - Navigator.push(context, MaterialPageRoute(builder: (context) => PlantAdded(plant: widget.plant, collController: widget.collectionController, plantType: widget.plantType)),); - }, - child: Card( - //color: Colors.green[300], - child: Padding( - padding: const EdgeInsets.all(10), - child: SizedBox( - width: 140, - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - mainAxisSize: MainAxisSize.min, - children: [ - ClipRRect( - borderRadius: BorderRadius.circular(10), - child: Container( - alignment: Alignment.center, - child: const Image( - image: AssetImage('assets/images/monstera.jpg'), - height: 140, - width: 140, - fit: BoxFit.fitWidth, - ), - ), - ), - const SizedBox(height: 9), - Expanded( - child: Align( - alignment: Alignment.topLeft, - child: Text( - collCont.colls[cindex].plantNames[index], - textAlign: TextAlign.start, - style: const TextStyle( - fontSize: 26, - fontWeight: FontWeight.w600, - height: 1, - leadingDistribution: TextLeadingDistribution.even, - ), - ), - ), - ), - Align( - alignment: Alignment.topLeft, - child: Text( - overflow: TextOverflow.ellipsis, - plantCont - .plants[collCont.colls[cindex].plantIds[index] - 1] - .latin, - style: const TextStyle( - fontSize: 18, - fontWeight: FontWeight.w400, - color: Colors.black54, - height: 1.0, - leadingDistribution: TextLeadingDistribution.even, - ), - ), - ) - ], - ), - ), - ), - ), - ); - }, - ); -} - -} - + Widget _contentGridView(int cindex) { + return GridView.builder( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, childAspectRatio: 0.67), + itemCount: collCont.colls[cindex].plantIds.length, + itemBuilder: (context, index) { + return Card( + //color: Colors.green[300], + child: Padding( + padding: const EdgeInsets.all(10), + child: SizedBox( + width: 140, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + mainAxisSize: MainAxisSize.min, + children: [ + ClipRRect( + borderRadius: BorderRadius.circular(10), + child: Container( + alignment: Alignment.center, + child: const Image( + image: AssetImage( + 'assets/images/monstera.jpg'), + height: 140, + width: 140, + fit: BoxFit.fitWidth, + ))), + const SizedBox(height: 9), + Expanded( + child: Align( + alignment: Alignment.topLeft, + child: Text( + collCont.colls[cindex].plantNames[index], + textAlign: TextAlign.start, + style: const TextStyle( + fontSize: 26, + fontWeight: FontWeight.w600, + height: 1, + leadingDistribution: + TextLeadingDistribution.even), + ), + ), + ), + Align( + alignment: Alignment.topLeft, + child: Text( + overflow: TextOverflow.ellipsis, + plantCont + .plants[ + collCont.colls[cindex].plantIds[index] - + 1] + .latin, + style: const TextStyle( + fontSize: 18, + fontWeight: FontWeight.w400, + color: Colors.black54, + height: 1.0, + leadingDistribution: + TextLeadingDistribution.even), + ), + ) + ])))); + }); + } +} \ No newline at end of file