šÆ Objective
Create a menu-driven to-do list application that demonstrates loops, lists, user input handling, and CRUD operations (Create, Read, Update, Delete).
Requirements
- Display a menu with 5 options: Add, View, Complete, Remove, Exit
- Store tasks using a Task class with description and completion status
- Add tasks with descriptions (prevent empty tasks)
- View all tasks with their status (ā³ Pending or ā
Completed)
- Mark tasks as completed by their list number
- Remove tasks from the list
- Show task statistics (completed vs pending count)
- Loop until user chooses to exit
Expected Output
āāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā To-Do List Manager ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāā
1. ā Add Task
2. š View Tasks
3. ā
Complete Task
4. šļø Remove Task
5. šŖ Exit
Choose an option (1-5): 1
Enter task description: Learn Dart programming
ā
Task added! Total tasks: 1
Choose an option (1-5): 1
Enter task description: Build a CLI app
ā
Task added! Total tasks: 2
Choose an option (1-5): 2
--- Your Tasks ---
1. ā³ Pending | Learn Dart programming
2. ā³ Pending | Build a CLI app
š Completed: 0 | Pending: 2
Step-by-Step Hints
š” Hint 1: Task Class
Create a Task class with description (String) and isCompleted (bool) properties. Override toString() for clean display.
š” Hint 2: Input Validation
Always check if the task list is empty before viewing, completing, or removing. Check for valid numbers when user selects a task to modify.
import 'dart:io';
// Step 1: Task class for better organization
class Task {
String description;
bool isCompleted;
DateTime createdAt;
Task(this.description, {this.isCompleted = false})
: createdAt = DateTime.now();
String get status => isCompleted ? 'ā
Completed' : 'ā³ Pending';
@override
String toString() {
return '[$status] $description';
}
}
void main() {
// Step 2: Initialize task list
List tasks = [];
bool running = true;
print('āāāāāāāāāāāāāāāāāāāāāāāāāāāā');
print('ā To-Do List Manager ā');
print('āāāāāāāāāāāāāāāāāāāāāāāāāāāā');
// Step 3: Main program loop
while (running) {
print('\n1. ā Add Task');
print('2. š View Tasks');
print('3. ā
Complete Task');
print('4. šļø Remove Task');
print('5. šŖ Exit');
stdout.write('\nChoose an option (1-5): ');
String? choice = stdin.readLineSync();
switch (choice) {
case '1':
addTask(tasks);
break;
case '2':
viewTasks(tasks);
break;
case '3':
completeTask(tasks);
break;
case '4':
removeTask(tasks);
break;
case '5':
running = false;
print('\nš Goodbye! You completed ${tasks.where((t) => t.isCompleted).length} tasks.');
break;
default:
print('ā ļø Invalid option. Please choose 1-5.');
}
}
}
// Step 4: Add task function
void addTask(List tasks) {
stdout.write('Enter task description: ');
String? description = stdin.readLineSync();
if (description == null || description.trim().isEmpty) {
print('ā ļø Task description cannot be empty.');
return;
}
tasks.add(Task(description.trim()));
print('ā
Task added! Total tasks: ${tasks.length}');
}
// Step 5: View tasks function
void viewTasks(List tasks) {
if (tasks.isEmpty) {
print('\nš No tasks yet. Add some tasks first!');
return;
}
print('\n--- Your Tasks ---');
for (int i = 0; i < tasks.length; i++) {
print('${i + 1}. ${tasks[i]}');
}
// Show statistics
int completed = tasks.where((t) => t.isCompleted).length;
int pending = tasks.length - completed;
print('\nš Completed: $completed | Pending: $pending');
}
// Step 6: Complete task function
void completeTask(List tasks) {
if (tasks.isEmpty) {
print('\nš No tasks to complete.');
return;
}
viewTasks(tasks);
stdout.write('\nEnter task number to mark as complete: ');
String? input = stdin.readLineSync();
int? taskNum = int.tryParse(input ?? '');
if (taskNum == null || taskNum < 1 || taskNum > tasks.length) {
print('ā ļø Invalid task number. Please enter 1-${tasks.length}.');
return;
}
Task task = tasks[taskNum - 1];
if (task.isCompleted) {
print('ā ļø Task "${task.description}" is already completed.');
} else {
task.isCompleted = true;
print('š Task "${task.description}" marked as completed!');
}
}
// Step 7: Remove task function
void removeTask(List tasks) {
if (tasks.isEmpty) {
print('\nš No tasks to remove.');
return;
}
viewTasks(tasks);
stdout.write('\nEnter task number to remove: ');
String? input = stdin.readLineSync();
int? taskNum = int.tryParse(input ?? '');
if (taskNum == null || taskNum < 1 || taskNum > tasks.length) {
print('ā ļø Invalid task number. Please enter 1-${tasks.length}.');
return;
}
// Confirm removal
Task taskToRemove = tasks[taskNum - 1];
stdout.write('Are you sure you want to remove "${taskToRemove.description}"? (y/n): ');
String? confirm = stdin.readLineSync()?.toLowerCase();
if (confirm == 'y' || confirm == 'yes') {
tasks.removeAt(taskNum - 1);
print('šļø Task removed. Remaining tasks: ${tasks.length}');
} else {
print('ā Removal cancelled.');
}
}