114 lines
3.3 KiB
Dart
114 lines
3.3 KiB
Dart
import 'package:flutter/material.dart';
|
|
|
|
import '../../core/app_state.dart';
|
|
import '../../core/app_theme.dart';
|
|
import '../../core/courses/courses.dart';
|
|
import '../../widgets/app_widgets.dart';
|
|
|
|
/// 课程路径:全部课程按顺序排列,显示完成、当前与锁定状态。
|
|
class LessonPath extends StatelessWidget {
|
|
const LessonPath({
|
|
super.key,
|
|
required this.state,
|
|
required this.onOpenLesson,
|
|
});
|
|
final AppState state;
|
|
final ValueChanged<String> onOpenLesson;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final done = allLessons
|
|
.where((lesson) => state.completedLessonIds.contains(lesson.id))
|
|
.length;
|
|
return SpacedColumn(
|
|
spacing: 10,
|
|
children: [
|
|
Row(
|
|
children: [
|
|
Expanded(
|
|
child: Text(
|
|
'课程路径',
|
|
style: Theme.of(context).textTheme.titleMedium,
|
|
),
|
|
),
|
|
Text(
|
|
'$done/${allLessons.length} 完成',
|
|
style: TextStyle(fontSize: 13, color: AppColors.muted),
|
|
),
|
|
],
|
|
),
|
|
if (state.reviewBacklog)
|
|
Text(
|
|
'复习有积压:先完成到期复习,新课暂时锁定;已学课程仍可重温。',
|
|
style: TextStyle(fontSize: 13, color: AppColors.warmInk),
|
|
),
|
|
for (final lesson in allLessons)
|
|
_LessonTile(
|
|
lesson: lesson,
|
|
state: state,
|
|
onTap: () => onOpenLesson(lesson.id),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
}
|
|
|
|
class _LessonTile extends StatelessWidget {
|
|
const _LessonTile({
|
|
required this.lesson,
|
|
required this.state,
|
|
required this.onTap,
|
|
});
|
|
final SeedLesson lesson;
|
|
final AppState state;
|
|
final VoidCallback onTap;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final completed = state.completedLessonIds.contains(lesson.id);
|
|
final current = lesson.id == state.activeLessonId && !completed;
|
|
final open =
|
|
state.isLessonUnlocked(lesson.id) &&
|
|
(!state.reviewBacklog || completed);
|
|
final segments = lesson.segments.length;
|
|
final segmentsDone = lesson.segments
|
|
.where((segment) => state.isSegmentComplete(segment.id))
|
|
.length;
|
|
return SectionCard(
|
|
tint: current ? AppColors.softGreen : null,
|
|
onTap: open ? onTap : null,
|
|
child: Row(
|
|
children: [
|
|
Icon(
|
|
completed
|
|
? Icons.check_circle
|
|
: open
|
|
? Icons.play_circle_outline
|
|
: Icons.lock_outline,
|
|
color: completed || current ? AppColors.green : AppColors.muted,
|
|
),
|
|
const SizedBox(width: 10),
|
|
Expanded(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
'第 ${lesson.number} 课 · ${lesson.title}',
|
|
style: const TextStyle(fontWeight: FontWeight.w600),
|
|
),
|
|
const SizedBox(height: 3),
|
|
Text(
|
|
segments > 1
|
|
? '${lesson.outcome} · 小段 $segmentsDone/$segments'
|
|
: lesson.outcome,
|
|
style: Theme.of(context).textTheme.bodyMedium,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|