Skip to content

Commit

Permalink
fix: reorder chart show not keep alive
Browse files Browse the repository at this point in the history
  • Loading branch information
evan361425 committed Mar 25, 2024
1 parent b220d87 commit a5e0a8e
Show file tree
Hide file tree
Showing 8 changed files with 107 additions and 24 deletions.
31 changes: 30 additions & 1 deletion lib/ui/analysis/widgets/chart_card_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class ChartCardView extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ReloadableCard<List>(
id: chart.name,
id: chart.id,
wrappedByCard: false,
notifiers: [range, chart, Seller.instance],
builder: (context, metric) {
Expand Down Expand Up @@ -177,6 +177,35 @@ class _CircularChart extends StatelessWidget {

@override
Widget build(BuildContext context) {
if (metrics.every((e) => e.value == 0)) {
return SfCircularChart(
tooltipBehavior: TooltipBehavior(
enable: true,
activationMode: ActivationMode.singleTap,
animationDuration: 150,
format: 'point.x : 0',
),
legend: const Legend(isVisible: true),
series: [
PieSeries<OrderMetricPerItem, String>(
animationDuration: 0,
explode: false, // show larger section when tap
name: chart.target.name,
xValueMapper: (v, i) => v.name,
yValueMapper: (v, i) => 1,
dataSource: metrics,
dataLabelMapper: (v, i) => '0%',
dataLabelSettings: const DataLabelSettings(
isVisible: true,
labelPosition: ChartDataLabelPosition.inside,
overflowMode: OverflowMode.shift,
labelIntersectAction: LabelIntersectAction.none,
),
),
],
);
}

return SfCircularChart(
tooltipBehavior: TooltipBehavior(
enable: true,
Expand Down
17 changes: 11 additions & 6 deletions lib/ui/analysis/widgets/chart_order_modal.dart
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,10 @@ class _ChartOrderModalState extends State<ChartOrderModal>
selected: type == e,
label: Text(S.analysisChartType(e.name)),
onSelected: (bool value) {
type = e;
_updateTarget(_allowedTargets.first);
setState(() {
type = e;
_updateTarget(_allowedTargets.first);
_updateTargetItem(_allowedTargets.first);
});
},
);
Expand All @@ -98,8 +99,9 @@ class _ChartOrderModalState extends State<ChartOrderModal>
label: Text(S.analysisChartTarget(e.name)),
onSelected: (bool value) {
if (value && target != e) {
_updateTarget(e);
setState(() {
_updateTarget(e);
_updateTargetItem(e);
});
}
},
Expand Down Expand Up @@ -226,7 +228,7 @@ class _ChartOrderModalState extends State<ChartOrderModal>
);
case AnalysisChartType.circular:
return SfCircularChart(
title: const ChartTitle(text: '範例'),
title: const ChartTitle(),
selectionGesture: ActivationMode.none,
series: <CircularSeries>[
PieSeries<int, int>(
Expand Down Expand Up @@ -325,10 +327,13 @@ class _ChartOrderModalState extends State<ChartOrderModal>
target = e;
metrics.clear();
metrics.add(_allowedMetrics.first);
targetItems.clear();
}

/// separate from [_updateTarget] to avoid check-mark dynamically change the ChoiceChip width
void _updateTargetItem(OrderMetricTarget e) {
targetItems.clear();
if (_singleTargetItem) {
targetItems.add(target.getItems().first.name);
targetItems.add(e.getItems().first.name);
}
}
}
2 changes: 1 addition & 1 deletion lib/ui/analysis/widgets/goals_card_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class _GoalsCardViewState extends State<GoalsCardView> {
Widget build(BuildContext context) {
return ReloadableCard<OrderDataPerDay>(
id: 'goals',
title: '目標',
title: '本日總結',
notifiers: [Seller.instance],
builder: _builder,
loader: _loader,
Expand Down
19 changes: 16 additions & 3 deletions lib/ui/analysis/widgets/reloadable_card.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@ class ReloadableCard<T> extends StatefulWidget {
final List<ChangeNotifier>? notifiers;

/// Required if you want to reload the card when it's visible.
final String? id;
final String id;

final String? title;

final bool wrappedByCard;

const ReloadableCard({
super.key,
this.id,
required this.id,
required this.builder,
required this.loader,
this.title,
Expand Down Expand Up @@ -63,7 +63,20 @@ class _ReloadableCardState<T> extends State<ReloadableCard<T>>
}

@override
bool get wantKeepAlive => true;
void didUpdateWidget(covariant ReloadableCard<T> oldWidget) {
// after reorder, the widget will be updated
if (oldWidget.id != widget.id) {
data = null;
reloadable = true;
reload();
updateKeepAlive();
}

super.didUpdateWidget(oldWidget);
}

@override
bool get wantKeepAlive => data != null;

/// Main content of the card
Widget buildTarget() {
Expand Down
25 changes: 19 additions & 6 deletions test/ui/analysis/analysis_view_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'package:mockito/mockito.dart';
import 'package:possystem/constants/icons.dart';
import 'package:possystem/helpers/util.dart';
import 'package:possystem/models/analysis/analysis.dart';
import 'package:possystem/models/analysis/chart.dart';
import 'package:possystem/models/repository/seller.dart';
import 'package:possystem/routes.dart';
import 'package:possystem/settings/currency_setting.dart';
Expand Down Expand Up @@ -101,7 +102,18 @@ void main() {
});

testWidgets('interact with chart', (tester) async {
Analysis();
Analysis().replaceItems({
'origin': Chart(
id: 'origin',
name: 'origin',
index: 1,
type: AnalysisChartType.cartesian,
ignoreEmpty: false,
target: OrderMetricTarget.order,
metrics: const [OrderMetricType.price],
targetItems: [],
),
});
mockGetChart();
when(storage.add(any, any, any)).thenAnswer((_) => Future.value());

Expand All @@ -116,7 +128,7 @@ void main() {
await tester.tap(find.byKey(const Key('modal.save')));
await tester.pumpAndSettle();

final chart = Analysis.instance.items.first;
final chart = Analysis.instance.items.last;
verify(storage.add(
any,
argThat(equals(chart.id)),
Expand All @@ -132,6 +144,7 @@ void main() {
expect(chart.target, OrderMetricTarget.order);
expect(chart.metrics, equals(const [OrderMetricType.price]));
expect(chart.targetItems, isEmpty);
expect(chart.index, 0);

// reorder
await tester.tap(find.byIcon(Icons.settings_sharp));
Expand All @@ -150,7 +163,7 @@ void main() {
expect(find.text(range.format(format)), findsOneWidget);

await tester.tap(find.byIcon(Icons.arrow_back_ios_new_sharp));
await tester.pumpAndSettle();
await tester.pump(const Duration(milliseconds: 50));

range = Util.getDateRange(
now: DateTime.now().subtract(const Duration(days: 14)),
Expand All @@ -159,7 +172,7 @@ void main() {
expect(find.text(range.format(format)), findsOneWidget);

await tester.tap(find.byIcon(Icons.arrow_forward_ios_sharp));
await tester.pumpAndSettle();
await tester.pump(const Duration(milliseconds: 50));

range = Util.getDateRange(
now: DateTime.now().subtract(const Duration(days: 7)),
Expand All @@ -171,8 +184,8 @@ void main() {
await tester.tap(find.byKey(const Key('anal.chart_range')));
await tester.pumpAndSettle();
await tester.tap(find.text('OK'));
await tester.pumpAndSettle();
expect(find.text(range.format(format)), findsOneWidget);
await tester.pump(const Duration(milliseconds: 50));
expect(find.text(range.format(format)), findsAtLeastNWidgets(1));
});

setUpAll(() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ import 'package:possystem/ui/analysis/widgets/chart_card_view.dart';
import 'package:syncfusion_flutter_charts/charts.dart';
import 'package:visibility_detector/visibility_detector.dart';

import '../../mocks/mock_database.dart';
import '../../mocks/mock_storage.dart';
import '../../test_helpers/translator.dart';
import '../../../mocks/mock_database.dart';
import '../../../mocks/mock_storage.dart';
import '../../../test_helpers/translator.dart';

void main() {
group('Chart Card View', () {
Expand Down Expand Up @@ -449,6 +449,29 @@ void main() {
})),
));
});

testWidgets('all metrics are zero', (tester) async {
Menu().replaceItems({
'c1': Catalog(id: 'c1', name: 'c1'),
'c2': Catalog(id: 'c2', name: 'c2'),
});
mockGetMetricsByItems(
table: equals(OrderMetricTarget.catalog.table),
rows: [
{'name': 'c1', 'value': 0},
{'name': 'c2', 'value': 0},
],
);

await tester.pumpWidget(buildApp(Chart(
type: AnalysisChartType.circular,
target: OrderMetricTarget.catalog,
)));
await tester.pumpAndSettle();

expect(find.text('c1', findRichText: true), findsOneWidget);
expect(find.text('c2', findRichText: true), findsOneWidget);
});
});

testWidgets('cartesian change to circular', (tester) async {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import 'package:intl/intl.dart';
import 'package:possystem/helpers/util.dart';
import 'package:possystem/ui/analysis/widgets/chart_range_page.dart';

import '../../test_helpers/translator.dart';
import '../../../test_helpers/translator.dart';

void main() {
group('Chart Range Page', () {
Expand Down Expand Up @@ -39,7 +39,7 @@ void main() {
await tester.pumpAndSettle();

expect(find.text('最近7日'), findsOneWidget);
expect(find.text(range.format(format)), findsOneWidget);
expect(find.text(range.format(format)), findsAtLeastNWidgets(1));
expect(find.text('本週'), findsOneWidget);
expect(find.text('上週'), findsOneWidget);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import 'package:possystem/models/repository/seller.dart';
import 'package:possystem/ui/analysis/widgets/goals_card_view.dart';
import 'package:visibility_detector/visibility_detector.dart';

import '../../mocks/mock_cache.dart';
import '../../mocks/mock_database.dart';
import '../../../mocks/mock_cache.dart';
import '../../../mocks/mock_database.dart';

void main() {
Future<List<Map<String, Object?>>> mockQuery(int begin, int cease) {
Expand Down

0 comments on commit a5e0a8e

Please sign in to comment.