Skip to content

Commit

Permalink
feat: analysis chart (#204)
Browse files Browse the repository at this point in the history
* fix: redirect if going to root

* chore: refactor number pretty string to util

* feat: add chart

* item modal padding only when needed

* ui test done

* fix: using PopScope

* fix origin test

* fix: use handleFieldSubmit

* fix: add target in cartesian

* fix lint

* fulfill test

* remove groupTo

* fulfill test
  • Loading branch information
evan361425 authored Mar 3, 2024
1 parent 51c50ca commit aa32a6a
Show file tree
Hide file tree
Showing 68 changed files with 2,991 additions and 483 deletions.
2 changes: 1 addition & 1 deletion .vscode/arb.code-snippets
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
"scope": "json",
"prefix": "select",
"body": [
"\"${1:name}\": \"{${2:placeholder}, select, other{$3}}\",",
"\"${1:name}\": \"{${2:placeholder}, select, other{${3:UNKNOWN}}}\",",
"\"@$1\": {",
"\t\"description\": \"${0:description}\",",
"\t\"placeholders\": {",
Expand Down
2 changes: 2 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,13 @@
"mockito",
"possystem",
"pubspec",
"reloadable",
"reorderable",
"sembast",
"signin",
"sqflite",
"sublist",
"syncfusion",
"unfocus",
"upgrader",
"vsync",
Expand Down
100 changes: 96 additions & 4 deletions docs/untranslated.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
"btnDelete",
"btnImport",
"btnExport",
"singleChoice",
"multiChoices",
"totalCount",
"searchCount",
"dialogDeletionContent",
Expand Down Expand Up @@ -178,7 +180,28 @@
"transitGSImportError",
"transitPreviewImportTitle",
"transitImportColumnsCountError",
"transitImportColumnStatus"
"transitImportColumnStatus",
"analysisChartCreate",
"analysisChartNameLabel",
"analysisChartWithTodayLabel",
"analysisChartIgnoreEmptyLabel",
"analysisChartIgnoreEmptyHelper",
"analysisChartRangeLabel",
"analysisChartRangeHelper",
"analysisChartRange",
"analysisChartTypeLabel",
"analysisChartType",
"analysisChartDataPropertiesDivider",
"analysisChartMetricLabel",
"analysisChartMetricHelper",
"analysisChartMetric",
"analysisChartTargetLabel",
"analysisChartTargetHelper",
"analysisChartTargetError",
"analysisChartTarget",
"analysisChartTargetItemLabel",
"analysisChartTargetItemHelper",
"analysisChartTargetItemSelectAll"
],

"zh_Hant": [
Expand All @@ -189,6 +212,8 @@
"btnDelete",
"btnImport",
"btnExport",
"singleChoice",
"multiChoices",
"totalCount",
"searchCount",
"dialogDeletionTitle",
Expand Down Expand Up @@ -425,7 +450,28 @@
"transitGSImportError",
"transitPreviewImportTitle",
"transitImportColumnsCountError",
"transitImportColumnStatus"
"transitImportColumnStatus",
"analysisChartCreate",
"analysisChartNameLabel",
"analysisChartWithTodayLabel",
"analysisChartIgnoreEmptyLabel",
"analysisChartIgnoreEmptyHelper",
"analysisChartRangeLabel",
"analysisChartRangeHelper",
"analysisChartRange",
"analysisChartTypeLabel",
"analysisChartType",
"analysisChartDataPropertiesDivider",
"analysisChartMetricLabel",
"analysisChartMetricHelper",
"analysisChartMetric",
"analysisChartTargetLabel",
"analysisChartTargetHelper",
"analysisChartTargetError",
"analysisChartTarget",
"analysisChartTargetItemLabel",
"analysisChartTargetItemHelper",
"analysisChartTargetItemSelectAll"
],

"zh_Hant_TW": [
Expand All @@ -436,6 +482,8 @@
"btnDelete",
"btnImport",
"btnExport",
"singleChoice",
"multiChoices",
"totalCount",
"searchCount",
"dialogDeletionTitle",
Expand Down Expand Up @@ -672,7 +720,28 @@
"transitGSImportError",
"transitPreviewImportTitle",
"transitImportColumnsCountError",
"transitImportColumnStatus"
"transitImportColumnStatus",
"analysisChartCreate",
"analysisChartNameLabel",
"analysisChartWithTodayLabel",
"analysisChartIgnoreEmptyLabel",
"analysisChartIgnoreEmptyHelper",
"analysisChartRangeLabel",
"analysisChartRangeHelper",
"analysisChartRange",
"analysisChartTypeLabel",
"analysisChartType",
"analysisChartDataPropertiesDivider",
"analysisChartMetricLabel",
"analysisChartMetricHelper",
"analysisChartMetric",
"analysisChartTargetLabel",
"analysisChartTargetHelper",
"analysisChartTargetError",
"analysisChartTarget",
"analysisChartTargetItemLabel",
"analysisChartTargetItemHelper",
"analysisChartTargetItemSelectAll"
],

"zh_TW": [
Expand All @@ -683,6 +752,8 @@
"btnDelete",
"btnImport",
"btnExport",
"singleChoice",
"multiChoices",
"totalCount",
"searchCount",
"dialogDeletionTitle",
Expand Down Expand Up @@ -919,6 +990,27 @@
"transitGSImportError",
"transitPreviewImportTitle",
"transitImportColumnsCountError",
"transitImportColumnStatus"
"transitImportColumnStatus",
"analysisChartCreate",
"analysisChartNameLabel",
"analysisChartWithTodayLabel",
"analysisChartIgnoreEmptyLabel",
"analysisChartIgnoreEmptyHelper",
"analysisChartRangeLabel",
"analysisChartRangeHelper",
"analysisChartRange",
"analysisChartTypeLabel",
"analysisChartType",
"analysisChartDataPropertiesDivider",
"analysisChartMetricLabel",
"analysisChartMetricHelper",
"analysisChartMetric",
"analysisChartTargetLabel",
"analysisChartTargetHelper",
"analysisChartTargetError",
"analysisChartTarget",
"analysisChartTargetItemLabel",
"analysisChartTargetItemHelper",
"analysisChartTargetItemSelectAll"
]
}
40 changes: 20 additions & 20 deletions lib/components/mixin/item_modal.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,6 @@ mixin ItemModal<T extends StatefulWidget> on State<T> {

String get title;

Widget buildBody() {
final fields = buildFormFields()
.expand((field) => [field, const SizedBox(height: kSpacing2)])
.toList();
fields.removeLast();

return SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(kSpacing3),
child: Center(child: buildForm(fields)),
),
);
}

@override
Widget build(BuildContext context) {
return Scaffold(
Expand All @@ -37,29 +23,35 @@ mixin ItemModal<T extends StatefulWidget> on State<T> {
),
],
),
body: buildBody(),
body: buildForm(),
);
}

Widget buildForm(List<Widget> fields) {
return Form(
key: formKey,
child: Column(
children: fields,
Widget buildForm() {
return SingleChildScrollView(
child: Form(
key: formKey,
child: Column(children: buildFormFields()),
),
);
}

/// Fields in form
List<Widget> buildFormFields();

/// Handle submission from input field (e.g. onFieldSubmitted)
void handleFieldSubmit(String _) {
handleSubmit();
}

/// Handle user submission
Future<void> handleSubmit() async {
if (isSaving || !_validate()) return;

await updateItem();
}

/// Update item implementation, called when the form is valid
Future<void> updateItem();

bool _validate() {
Expand All @@ -73,4 +65,12 @@ mixin ItemModal<T extends StatefulWidget> on State<T> {

return true;
}

/// Padding widget
Widget p(Widget child) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: kSpacing3),
child: child,
);
}
}
83 changes: 41 additions & 42 deletions lib/components/scrollable_draggable_sheet.dart
Original file line number Diff line number Diff line change
Expand Up @@ -47,38 +47,28 @@ class _ScrollableDraggableSheetState extends State<ScrollableDraggableSheet> {

@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async {
final willPop = controller.snapIndex.value == 0;
if (!willPop) {
controller.reset();
}

return willPop;
return LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
controller.transferSnapSizes(
constraints.biggest.height,
widget.margin.vertical,
);

return DraggableScrollableSheet(
controller: controller,
initialChildSize: controller.snapSizes[widget.initSnapIndex],
minChildSize: controller.minSnap,
maxChildSize: controller.maxSnap,
expand: true,
snap: true,
snapSizes: controller.snapSizes,
shouldCloseOnMinExtent: true,
builder: (_, scrollController) {
scroll = scrollController;
return content;
},
);
},
child: LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
controller.transferSnapSizes(
constraints.biggest.height,
widget.margin.vertical,
);

return DraggableScrollableSheet(
controller: controller,
initialChildSize: controller.snapSizes[widget.initSnapIndex],
minChildSize: controller.minSnap,
maxChildSize: controller.maxSnap,
expand: true,
snap: true,
snapSizes: controller.snapSizes,
shouldCloseOnMinExtent: true,
builder: (_, scrollController) {
scroll = scrollController;
return content;
},
);
},
),
);
}

Expand Down Expand Up @@ -129,18 +119,27 @@ class _ScrollableDraggableSheetState extends State<ScrollableDraggableSheet> {
if (value == 1.0) {
scrollable.value = true;
}
return Card(
shape: value == 1.0
? const RoundedRectangleBorder(borderRadius: BorderRadius.zero)
: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(
top: Radius.circular(16.0),
return PopScope(
canPop: controller.snapIndex.value == 0,
onPopInvoked: (popped) {
if (!popped) {
controller.reset();
}
},
child: Card(
shape: value == 1.0
? const RoundedRectangleBorder(
borderRadius: BorderRadius.zero)
: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(
top: Radius.circular(16.0),
),
),
),
clipBehavior: Clip.hardEdge,
elevation: 2.0,
margin: value == 1.0 ? const EdgeInsets.all(0) : widget.margin,
child: child,
clipBehavior: Clip.hardEdge,
elevation: 2.0,
margin: value == 1.0 ? const EdgeInsets.all(0) : widget.margin,
child: child,
),
);
},
child: Column(
Expand Down
2 changes: 1 addition & 1 deletion lib/components/style/outlined_text.dart
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class OutlinedText extends StatelessWidget {
const EdgeInsets.symmetric(horizontal: 16),
const EdgeInsets.symmetric(horizontal: 8),
const EdgeInsets.symmetric(horizontal: 4),
MediaQuery.maybeOf(context)?.textScaleFactor ?? 1,
MediaQuery.textScalerOf(context).scale(1),
);

final base = ConstrainedBox(
Expand Down
17 changes: 2 additions & 15 deletions lib/components/style/percentile_bar.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:possystem/helpers/util.dart';

class PercentileBar extends StatefulWidget {
final num total;
Expand Down Expand Up @@ -28,9 +29,7 @@ class _PercentileBarState extends State<PercentileBar>
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text(_toString(widget.at)),
const Text('/'),
Text(_toString(widget.total)),
Text('${widget.at.prettyString()}/${widget.total.prettyString()}'),
],
),
AnimatedBuilder(
Expand Down Expand Up @@ -99,15 +98,3 @@ class _PercentileBarState extends State<PercentileBar>
super.dispose();
}
}

/// Maximum 4 characters
String _toString(num v) {
if (v is int || v == v.ceil()) {
if (v < 10000) {
return v.toStringAsFixed(0);
}
} else if (v < 1000) {
return v.toStringAsFixed(1);
}
return v.toStringAsExponential(1);
}
Loading

0 comments on commit aa32a6a

Please sign in to comment.