Commit f45a4bdc9f626208abe76901973e9793af0edc2e

Authored by 刘宏哲
1 parent 4602f5da

feat(app): bug fixed

... ... @@ -10,10 +10,9 @@ DateTime _today() {
}
class _ReportPeriodAnchor {
const _ReportPeriodAnchor({required this.date, this.sourceMonth});
const _ReportPeriodAnchor({required this.date});
final DateTime date;
final DateTime? sourceMonth;
}
abstract class ReportPeriodLogic {
... ... @@ -140,13 +139,9 @@ abstract class ReportPeriodLogic {
return Future.value();
}
final nextDate = _dateForPeriodTransition(nextPeriod);
final sourceMonth = selectedPeriod.value == ReportPeriod.month &&
nextPeriod == ReportPeriod.week
? monthStart
: null;
selectedPeriod.value = nextPeriod;
selectedDate.value = nextDate;
_setAnchorFor(nextPeriod, nextDate, sourceMonth: sourceMonth);
_setAnchorFor(nextPeriod, nextDate);
return loadReport();
}
... ... @@ -253,23 +248,12 @@ abstract class ReportPeriodLogic {
void dispose() {}
void _setAnchorFor(
ReportPeriod period,
DateTime date, {
DateTime? sourceMonth,
}) {
void _setAnchorFor(ReportPeriod period, DateTime date) {
final normalizedPeriod = normalizePeriod(period);
final normalizedDate = normalizeDate(normalizedPeriod, date);
final weekSourceMonth =
DateTime(normalizedDate.year, normalizedDate.month);
_anchor = switch (normalizedPeriod) {
ReportPeriod.day => _ReportPeriodAnchor(date: normalizedDate),
ReportPeriod.week => _ReportPeriodAnchor(
date: ReportDateRangeConfig.clampDate(
normalizedDate.add(const Duration(days: 6)),
),
sourceMonth: sourceMonth ?? weekSourceMonth,
),
ReportPeriod.week => _ReportPeriodAnchor(date: normalizedDate),
ReportPeriod.month => _ReportPeriodAnchor(
date: ReportDateRangeConfig.clampDate(
_lastDayOfMonth(normalizedDate),
... ... @@ -284,21 +268,6 @@ abstract class ReportPeriodLogic {
}
DateTime _dateForPeriodTransition(ReportPeriod nextPeriod) {
final currentPeriod = selectedPeriod.value;
if (currentPeriod == ReportPeriod.week &&
nextPeriod == ReportPeriod.month) {
// Preserve the source month when entering from a month. A directly
// selected week uses the month containing its Monday as the source.
return normalizeDate(nextPeriod, _anchor.sourceMonth ?? weekStart);
}
if (currentPeriod == ReportPeriod.week &&
nextPeriod == ReportPeriod.year) {
// A cross-year week belongs to the year containing its Monday.
return normalizeDate(nextPeriod, weekStart);
}
return normalizeDate(nextPeriod, _anchor.date);
}
... ...
import 'package:doublefeel_flutter/app/modules/report_common/config/report_date_range_config.dart';
import 'package:doublefeel_flutter/app/modules/report_common/controllers/report_period_logic.dart';
import 'package:doublefeel_flutter/app/modules/report_common/models/report_period.dart';
import 'package:flutter_test/flutter_test.dart';
... ... @@ -10,26 +9,6 @@ class _TestReportPeriodLogic extends ReportPeriodLogic {
Future<void> loadReport() async {}
}
class _MonthBoundaryReportPeriodLogic extends _TestReportPeriodLogic {
_MonthBoundaryReportPeriodLogic(this.sourceMonth);
final DateTime sourceMonth;
@override
DateTime normalizeDate(ReportPeriod period, DateTime date) {
if (period == ReportPeriod.week &&
date.year == sourceMonth.year &&
date.month == sourceMonth.month) {
// Simulates a month whose latest selectable week starts in the
// preceding month.
return sourceMonth.subtract(
Duration(days: sourceMonth.weekday - DateTime.monday),
);
}
return super.normalizeDate(period, date);
}
}
void main() {
group('ReportPeriodLogic period transitions', () {
test('year to month selects December for a completed year', () async {
... ... @@ -113,7 +92,7 @@ void main() {
);
});
test('month to week to month keeps the source month',
test('month to week to month uses the week start month',
() async {
final logic = _TestReportPeriodLogic();
final year = DateTime.now().year - 1;
... ... @@ -126,52 +105,19 @@ void main() {
expect(logic.monthStart, DateTime(year, DateTime.december));
});
test('clamped cross-month week returns to the original source month',
() async {
final year = DateTime.now().year - 1;
final sourceMonth = List<DateTime>.generate(
12,
(index) => DateTime(year, index + 1),
).firstWhere((month) => month.weekday != DateTime.monday);
final logic = _MonthBoundaryReportPeriodLogic(sourceMonth);
final clampedWeekStart = sourceMonth.subtract(
Duration(days: sourceMonth.weekday - DateTime.monday),
);
logic.initializeQuery(ReportPeriod.month, sourceMonth);
await logic.selectPeriod(ReportPeriod.week);
expect(logic.weekStart, clampedWeekStart);
await logic.selectPeriod(ReportPeriod.month);
expect(logic.monthStart, sourceMonth);
});
test('week to day selects Sunday when the whole week is selectable',
test('week to day selects Monday',
() async {
final logic = _TestReportPeriodLogic();
logic.initializeQuery(
ReportPeriod.week,
DateTime(DateTime.now().year - 1, 10, 20),
);
final expectedDay = logic.weekEnd;
final expectedDay = logic.weekStart;
await logic.selectPeriod(ReportPeriod.day);
expect(logic.selectedDate.value, expectedDay);
});
test('week to day clamps a partial latest week to the latest date',
() async {
final logic = _TestReportPeriodLogic();
logic.initializeQuery(
ReportPeriod.week,
ReportDateRangeConfig.lastWeekStart(),
);
await logic.selectPeriod(ReportPeriod.day);
expect(logic.selectedDate.value, ReportDateRangeConfig.lastDate());
});
});
}
... ...