-
Notifications
You must be signed in to change notification settings - Fork 1.3k
feat: Add Tomorrow category to Tasks page #3957
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
- Added Tomorrow category between Today and No Deadline - Tasks due tomorrow are now shown in their own section - Updated both mobile and desktop versions - Drag a task to Tomorrow sets deadline to tomorrow 11:59 PM 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request successfully adds the 'Tomorrow' category for tasks on both mobile and desktop versions. The logic for categorizing tasks and setting default due dates appears correct.
However, I've identified significant code duplication between the mobile (action_items_page.dart) and desktop (desktop_actions_page.dart) implementations. Several methods and the TaskCategory enum are duplicated, which will make future maintenance more difficult and error-prone. My main feedback is to refactor this shared logic into a common location, such as a mixin, to improve code reuse and maintainability. Please see my detailed comment.
| import 'package:omi/ui/atoms/omi_button.dart'; | ||
|
|
||
| enum TaskCategory { today, noDeadline, later } | ||
| enum TaskCategory { today, tomorrow, noDeadline, later } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is significant code duplication between this file and app/lib/pages/action_items/action_items_page.dart. The TaskCategory enum, and the methods _categorizeItems, _getCategoryTitle, _getDefaultDueDateForCategory, and _updateTaskCategory are nearly identical in both files.
This duplication makes the code harder to maintain. Any future changes to task categorization logic will need to be applied in two places, increasing the risk of inconsistencies and bugs.
To resolve this, I recommend extracting the shared logic into a mixin. This will promote code reuse and ensure that both the mobile and desktop views share the same business logic for handling task categories.
Here's an example of how this could be structured:
// In a new shared file, e.g., 'app/lib/features/action_items/task_categorization_mixin.dart'
import 'package:flutter/material.dart';
import 'package:omi/backend/schema/schema.dart';
import 'package:omi/providers/action_items_provider.dart';
import 'package:provider/provider.dart';
enum TaskCategory { today, tomorrow, noDeadline, later }
mixin TaskCategorization<T extends StatefulWidget> on State<T> {
Map<TaskCategory, List<ActionItemWithMetadata>> categorizeItems(
List<ActionItemWithMetadata> items, bool showCompleted) {
final now = DateTime.now();
final startOfTomorrow = DateTime(now.year, now.month, now.day + 1);
final startOfDayAfterTomorrow = DateTime(now.year, now.month, now.day + 2);
final sevenDaysAgo = now.subtract(const Duration(days: 7));
final Map<TaskCategory, List<ActionItemWithMetadata>> categorized = {
for (var category in TaskCategory.values) category: [],
};
for (var item in items) {
// Only show items that match the completion status filter.
if (item.completed != showCompleted) continue;
// Skip old tasks without a future due date (only for non-completed)
if (!showCompleted) {
if (item.dueAt != null) {
if (item.dueAt!.isBefore(sevenDaysAgo)) continue;
} else {
if (item.createdAt != null && item.createdAt!.isBefore(sevenDaysAgo)) continue;
}
}
if (item.dueAt == null) {
categorized[TaskCategory.noDeadline]!.add(item);
} else {
final dueDate = item.dueAt!;
if (dueDate.isBefore(startOfTomorrow)) {
categorized[TaskCategory.today]!.add(item);
} else if (dueDate.isBefore(startOfDayAfterTomorrow)) {
categorized[TaskCategory.tomorrow]!.add(item);
} else {
categorized[TaskCategory.later]!.add(item);
}
}
}
return categorized;
}
String getCategoryTitle(TaskCategory category) {
switch (category) {
case TaskCategory.today:
return 'Today';
case TaskCategory.tomorrow:
return 'Tomorrow';
case TaskCategory.noDeadline:
return 'No Deadline';
case TaskCategory.later:
return 'Later';
}
}
DateTime? getDefaultDueDateForCategory(TaskCategory category) {
final now = DateTime.now();
switch (category) {
case TaskCategory.today:
return DateTime(now.year, now.month, now.day, 23, 59);
case TaskCategory.tomorrow:
return DateTime(now.year, now.month, now.day + 1, 23, 59);
case TaskCategory.noDeadline:
return null;
case TaskCategory.later:
// Day after tomorrow
return DateTime(now.year, now.month, now.day + 2, 23, 59);
}
}
void updateTaskCategory(ActionItemWithMetadata item, TaskCategory newCategory) {
final provider = Provider.of<ActionItemsProvider>(context, listen: false);
final newDueDate = getDefaultDueDateForCategory(newCategory);
provider.updateActionItemDueDate(item, newDueDate);
}
}You can then apply this mixin to both DesktopActionsPageState and _ActionItemsPageState and remove the duplicated code from them.
Summary
Test plan
🤖 Generated with Claude Code