diff --git a/lib/enums/taskoptions.dart b/lib/enums/taskoptions.dart index 5a2c604..9763ac8 100644 --- a/lib/enums/taskoptions.dart +++ b/lib/enums/taskoptions.dart @@ -6,4 +6,5 @@ enum TaskOption { launchMeditationScreen, toggleTipVisibility, exportToCSV, + loadFromCSV, } diff --git a/lib/screens/home_screen.dart b/lib/screens/home_screen.dart index 9303db0..25345db 100644 --- a/lib/screens/home_screen.dart +++ b/lib/screens/home_screen.dart @@ -1,3 +1,4 @@ +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:fluttertoast/fluttertoast.dart'; @@ -190,6 +191,15 @@ class _HomeScreenState extends State { } else if (option == TaskOption.exportToCSV) { exportToCSV(tasks); } + else if (option == TaskOption.loadFromCSV) { + importFromCSV(tasks).then((newTasks) { + setState(() { + tasks = newTasks; + }); + TaskStorage.saveTasks(tasks); + }); + } + }); void _editTask(int index) async { final newTask = await Navigator.push( @@ -285,6 +295,63 @@ class _HomeScreenState extends State { print("File saved at: $path"); } +Future> importFromCSV(List existingTasks) async { + try { + FilePickerResult? result = await FilePicker.platform.pickFiles( + type: FileType.custom, + allowedExtensions: ['csv'], + ); + if (result == null) { + print("Import canceled."); + return existingTasks; + } + final file = File(result.files.single.path!); + final content = await file.readAsString(); + List> rows = const CsvToListConverter().convert(content); + if (rows.isEmpty) { + Fluttertoast.showToast(msg: "CSV file is empty"); + return existingTasks; + } + List expectedHeader = ["Title", "Description", "Is Completed", "Has Deadline", "Deadline"]; + List actualHeader = rows[0].map((e) => e.toString()).toList(); + if (!listEquals(expectedHeader, actualHeader)) { + Fluttertoast.showToast(msg: "Invalid CSV format. Please use the correct template"); + return existingTasks; + } + List importedTasks = []; + for (int i = 1; i < rows.length; i++) { + try { + var row = rows[i]; + DateTime? deadline; + if (row[4].toString().isNotEmpty) { + List dateParts = row[4].toString().split('/'); + deadline = DateTime( + int.parse(dateParts[2]), + int.parse(dateParts[1]), + int.parse(dateParts[0]), + ); + } + Task task = Task( + title: row[0].toString(), + description: row[1].toString(), + isCompleted: row[2].toString().toLowerCase() == 'true', + deadline: deadline ?? DateTime.now(), + ); + importedTasks.add(task); + } catch (e) { + print("Error parsing row $i: $e"); + Fluttertoast.showToast(msg: "Error parsing some tasks. Some entries might be skipped."); + } + } + existingTasks.addAll(importedTasks); + Fluttertoast.showToast(msg: "Successfully imported ${importedTasks.length} tasks"); + return existingTasks; + } catch (e) { + print("Import error: $e"); + Fluttertoast.showToast(msg: "Error importing CSV file"); + return existingTasks; + } +} void _loadKudos() async { Kudos loadedKudos = await KudosStorage.loadKudos(); setState(() { @@ -347,6 +414,10 @@ class _HomeScreenState extends State { value: TaskOption.launchMeditationScreen, child: Text("Meditate"), ), + const PopupMenuItem( + value: TaskOption.loadFromCSV, + child: Text("Load Tasks from csv file."), + ), ]; }, ),