Files
task_hub/lib/widgets/task_item.dart
2026-04-28 19:59:51 +08:00

189 lines
5.5 KiB
Dart

import 'package:fluent_ui/fluent_ui.dart';
import 'package:task_hub/models/task.dart';
class TaskItem extends StatelessWidget {
final Task task;
final VoidCallback onToggleComplete;
final VoidCallback onEdit;
final VoidCallback onDelete;
const TaskItem({
super.key,
required this.task,
required this.onToggleComplete,
required this.onEdit,
required this.onDelete,
});
@override
Widget build(BuildContext context) {
return Card(
child: Padding(
padding: const EdgeInsets.all(12.0),
child: Row(
children: [
Checkbox(
checked: task.isCompleted,
onChanged: (value) => onToggleComplete(),
),
const SizedBox(width: 12),
// 任务信息
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
_buildPriorityIndicator(task.priority),
const SizedBox(width: 8),
Expanded(child: _buildTitle(context)),
],
),
const SizedBox(height: 4),
if (task.desc != null && task.desc!.isNotEmpty) _buildDesc(),
const SizedBox(height: 4),
if (task.dueDate != null || task.scheduleTime != null)
_buildDate(),
],
),
),
Row(
children: [
IconButton(
icon: const Icon(FluentIcons.edit, size: 16),
onPressed: onEdit,
),
_buildDeleteButton(),
],
),
],
),
),
);
}
Widget _buildTitle(BuildContext context) {
return Text(
task.title,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
decoration: task.isCompleted ? TextDecoration.lineThrough : null,
color: task.isCompleted ? Colors.grey[100] : FluentTheme.of(context).accentColor,
),
);
}
Widget _buildDesc() {
return Text(
task.desc!,
style: TextStyle(
color: Colors.grey[150],
fontSize: 14,
decoration: task.isCompleted ? TextDecoration.lineThrough : null,
),
);
}
Widget _buildDate() {
return Row(
children: [
if (task.dueDate != null) ...[
Icon(FluentIcons.calendar, size: 12, color: Colors.grey),
const SizedBox(width: 4),
Text(
'截止日期: ${_formatDate(task.dueDate!)}',
style: TextStyle(color: Colors.grey, fontSize: 12),
),
const SizedBox(width: 4),
],
if (task.scheduleTime != null) ...[
Icon(FluentIcons.clock, size: 12, color: Colors.grey),
const SizedBox(width: 4),
Text(
'提醒日期: ${_formatDate(task.scheduleTime!)}',
style: TextStyle(color: Colors.grey, fontSize: 12),
),
],
],
);
}
Widget _buildPriorityIndicator(Priority priority) {
final Map<Priority, (Color, String)> priorityInfo = {
Priority.low: (Colors.grey, ''),
Priority.medium: (Colors.green, ''),
Priority.high: (Colors.red, ''),
};
final (color, label) = priorityInfo[priority]!;
return Container(
padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 3),
decoration: BoxDecoration(
color: color,
borderRadius: BorderRadius.circular(4),
),
child: Center(
child: Text(
label,
style: const TextStyle(
color: Colors.white,
fontSize: 10,
fontWeight: FontWeight.bold,
),
),
),
);
}
Widget _buildDeleteButton() {
final controller = FlyoutController();
return FlyoutTarget(
controller: controller,
child: IconButton(
icon: const Icon(FluentIcons.delete, size: 16),
onPressed: () {
controller.showFlyout<void>(
builder: (context) {
return FlyoutContent(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text('确认删除该任务?'),
const SizedBox(height: 12.0),
Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Button(
onPressed: () {
onDelete();
Flyout.of(context).close();
},
child: const Text('确认'),
),
const SizedBox(width: 5),
Button(
onPressed: Flyout.of(context).close,
child: const Text('取消'),
),
],
),
],
),
);
},
);
},
),
);
}
String _formatDate(DateTime date) {
return '${date.year}-${date.month.toString().padLeft(2, '0')}-${date.day.toString().padLeft(2, '0')}';
}
}