feat(train): Home opens on this week, its totals and its seven days (ADR 0030, D60)
The week's time, distance and workouts above Home's list, and a strip of its days, each as tall as the time trained on it, starting on the day the person's language starts weeks on. Home's empty hint points to the Record tab, where its button had gone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
7473366f66
commit
064c44bfa5
2 changed files with 502 additions and 13 deletions
|
|
@ -43,6 +43,7 @@ import 'package:halkyon_train_flutter/src/feature/route/data/routing_gateway.dar
|
|||
import 'package:halkyon_train_flutter/src/feature/route/model/route.dart';
|
||||
import 'package:halkyon_train_flutter/src/feature/workout/data/workout_repository.dart';
|
||||
import 'package:halkyon_train_flutter/src/feature/workout/model/workout.dart';
|
||||
import 'package:halkyon_train_flutter/src/feature/workout/widget/week_card.dart';
|
||||
import 'package:halkyon_ui/halkyon_ui.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:http/testing.dart';
|
||||
|
|
@ -2899,7 +2900,10 @@ void main() {
|
|||
expect(top('Morning run'), lessThan(top('September 2026')));
|
||||
expect(top('September 2026'), lessThan(top('Lakeside')));
|
||||
expect(top('Lakeside'), lessThan(top('Locked workout')));
|
||||
expect(find.text('2.50 km'), findsNWidgets(2));
|
||||
// In the list, not in the week above it.
|
||||
Finder listed(String text) =>
|
||||
find.descendant(of: find.byType(ListTile), matching: find.text(text));
|
||||
expect(listed('2.50 km'), findsNWidgets(2));
|
||||
expect(find.text('12:30'), findsNWidgets(2));
|
||||
expect(find.text('5:00 /km'), findsNWidgets(2));
|
||||
expect(find.text('30:00'), findsOneWidget);
|
||||
|
|
@ -2909,6 +2913,42 @@ void main() {
|
|||
);
|
||||
});
|
||||
|
||||
testWidgets('above them, this week: its time, distance and workouts, and '
|
||||
'its days from Monday in British English (D60)', (tester) async {
|
||||
tester.platformDispatcher.localesTestValue = const [Locale('en', 'GB')];
|
||||
addTearDown(tester.platformDispatcher.clearLocalesTestValue);
|
||||
// Saturday, 31 October 2026.
|
||||
await withClock(Clock.fixed(DateTime(2026, 10, 31, 15)), () async {
|
||||
await saveRun(DateTime(2026, 10, 27, 7, 30));
|
||||
await saveRow();
|
||||
// Sunday before: last week's.
|
||||
await saveRun(DateTime(2026, 10, 25, 9));
|
||||
await startWith(tester);
|
||||
|
||||
final week = find.byType(WeekCard);
|
||||
Finder inWeek(String text) =>
|
||||
find.descendant(of: week, matching: find.text(text));
|
||||
expect(inWeek('This week'), findsOneWidget);
|
||||
// 12:30 running and 30:00 rowing.
|
||||
expect(inWeek('42 min'), findsOneWidget);
|
||||
expect(inWeek('2.50 km'), findsOneWidget);
|
||||
expect(inWeek('2'), findsOneWidget);
|
||||
final letters = tester
|
||||
.widgetList<Text>(
|
||||
find.descendant(of: week, matching: find.byType(Text)),
|
||||
)
|
||||
.map((text) => text.data)
|
||||
.toList();
|
||||
expect(letters.sublist(letters.length - 7), [
|
||||
'M', 'T', 'W', 'T', 'F', 'S', 'S', //
|
||||
]);
|
||||
expect(
|
||||
tester.getTopLeft(week).dy,
|
||||
lessThan(tester.getTopLeft(find.text('October 2026')).dy),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
testWidgets("a workout's page shows its map, totals, splits and charts, "
|
||||
'and where the map comes from', (tester) async {
|
||||
await saveRun(DateTime(2026, 10, 27, 7, 30));
|
||||
|
|
|
|||
|
|
@ -0,0 +1,112 @@
|
|||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:halkyon_train_flutter/src/feature/workout/data/week_summary.dart';
|
||||
import 'package:halkyon_train_flutter/src/feature/workout/model/workout.dart';
|
||||
|
||||
/// The week Home sums up above the workouts (ADR 0030, D60): from the day
|
||||
/// the person's weeks start on, in their own time, each workout counted on
|
||||
/// the day it started.
|
||||
void main() {
|
||||
// Saturday, 31 October 2026, in the afternoon, local time.
|
||||
final now = DateTime(2026, 10, 31, 15);
|
||||
|
||||
WorkoutContent workout(
|
||||
DateTime start, {
|
||||
Duration length = const Duration(hours: 1),
|
||||
Duration? moving,
|
||||
int? metres,
|
||||
}) => WorkoutContent(
|
||||
activity: Activity.running,
|
||||
startedAt: start.toUtc(),
|
||||
endedAt: start.add(length).toUtc(),
|
||||
movingTime: moving,
|
||||
distanceMetres: metres,
|
||||
);
|
||||
|
||||
test('a week starting on Monday sums the workouts from Monday on', () {
|
||||
final week = weekSummary(
|
||||
[
|
||||
workout(
|
||||
DateTime(2026, 10, 26, 7),
|
||||
moving: const Duration(minutes: 40),
|
||||
metres: 8000,
|
||||
),
|
||||
workout(
|
||||
DateTime(2026, 10, 31, 9),
|
||||
moving: const Duration(minutes: 20),
|
||||
metres: 4500,
|
||||
),
|
||||
// Sunday before: last week.
|
||||
workout(DateTime(2026, 10, 25, 23, 30), metres: 10000),
|
||||
],
|
||||
now: now,
|
||||
firstDay: DateTime.monday,
|
||||
);
|
||||
|
||||
expect(week.start, DateTime(2026, 10, 26));
|
||||
expect(week.count, 2);
|
||||
expect(week.time, const Duration(hours: 1));
|
||||
expect(week.metres, 12500);
|
||||
expect(week.days.map((d) => d.weekday), [1, 2, 3, 4, 5, 6, 7]);
|
||||
expect(week.days.map((d) => d.time.inMinutes), [40, 0, 0, 0, 0, 20, 0]);
|
||||
expect(week.today, 5);
|
||||
});
|
||||
|
||||
test('a week starting on Sunday takes in the Sunday before', () {
|
||||
final week = weekSummary(
|
||||
[
|
||||
workout(DateTime(2026, 10, 25, 23, 30)),
|
||||
],
|
||||
now: now,
|
||||
firstDay: DateTime.sunday,
|
||||
);
|
||||
|
||||
expect(week.start, DateTime(2026, 10, 25));
|
||||
expect(week.days.first.weekday, DateTime.sunday);
|
||||
expect(week.days.first.time, const Duration(hours: 1));
|
||||
expect(week.today, 6);
|
||||
});
|
||||
|
||||
test('without its moving time a workout counts from start to end; '
|
||||
'without a distance, none', () {
|
||||
final week = weekSummary(
|
||||
[
|
||||
workout(
|
||||
DateTime(2026, 10, 27, 18),
|
||||
length: const Duration(minutes: 45),
|
||||
),
|
||||
],
|
||||
now: now,
|
||||
firstDay: DateTime.monday,
|
||||
);
|
||||
|
||||
expect(week.time, const Duration(minutes: 45));
|
||||
expect(week.metres, 0);
|
||||
expect(week.count, 1);
|
||||
});
|
||||
|
||||
test('a week without workouts is all naught', () {
|
||||
final week = weekSummary(const [], now: now, firstDay: DateTime.monday);
|
||||
|
||||
expect(week.count, 0);
|
||||
expect(week.time, Duration.zero);
|
||||
expect(week.days, hasLength(7));
|
||||
expect(week.longestDay, Duration.zero);
|
||||
});
|
||||
|
||||
test('the longest day scales the strip', () {
|
||||
final week = weekSummary(
|
||||
[
|
||||
workout(DateTime(2026, 10, 26, 7), moving: const Duration(minutes: 30)),
|
||||
workout(
|
||||
DateTime(2026, 10, 26, 18),
|
||||
moving: const Duration(minutes: 30),
|
||||
),
|
||||
workout(DateTime(2026, 10, 28, 7), moving: const Duration(minutes: 20)),
|
||||
],
|
||||
now: now,
|
||||
firstDay: DateTime.monday,
|
||||
);
|
||||
|
||||
expect(week.longestDay, const Duration(hours: 1));
|
||||
});
|
||||
}
|
||||
Loading…
Reference in a new issue