Commit 1f768ce2 authored by Collin Jackson's avatar Collin Jackson

First pass at adding meal tracking to fitness app

parent 6b748e65
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:sky/widgets/basic.dart';
import 'package:sky/widgets/card.dart';
import 'package:sky/widgets/dismissable.dart';
typedef void FitnessItemHandler(FitnessItem item);
const double kFitnessItemHeight = 79.0;
class FitnessItem {
FitnessItem({ this.when }) {
assert(when != null);
}
final DateTime when;
// TODO(jackson): Internationalize
String get displayDate => "${when.year.toString()}-${when.month.toString().padLeft(2,'0')}-${when.day.toString().padLeft(2,'0')}";
}
abstract class FitnessItemRow extends Component {
FitnessItemRow({ FitnessItem item, this.onDismissed })
: this.item = item,
super(key: item.when.toString());
final FitnessItem item;
final FitnessItemHandler onDismissed;
Widget buildContent();
Widget build() {
return new Dismissable(
onDismissed: () => onDismissed(item),
child: new Card(
child: new Container(
height: kFitnessItemHeight,
padding: const EdgeDims.all(8.0),
child: buildContent()
)
)
);
}
}
......@@ -2,5 +2,5 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
enum FitnessMode { measure, run }
enum FitnessMode { feed, chart }
enum BackupMode { enabled, disabled }
......@@ -9,31 +9,44 @@ import 'package:sky/widgets/theme.dart';
import 'package:sky/widgets/widget.dart';
import 'package:sky/widgets/task_description.dart';
import 'meal.dart';
import 'measurement.dart';
import 'home.dart';
import 'feed.dart';
import 'settings.dart';
import 'fitness_item.dart';
import 'fitness_types.dart';
class FitnessApp extends App {
NavigationState _navigationState;
final List<FitnessItem> _userData = [
new Measurement(weight: 180.0, when: new DateTime.now().add(const Duration(days: -1))),
new Measurement(weight: 160.0, when: new DateTime.now()),
];
void initState() {
_navigationState = new NavigationState([
new Route(
name: '/',
builder: (navigator, route) => new HomeFragment(
builder: (navigator, route) => new FeedFragment(
navigator: navigator,
userData: _userData,
onMeasurementCreated: _handleMeasurementCreated,
onMeasurementDeleted: _handleMeasurementDeleted
onItemCreated: _handleItemCreated,
onItemDeleted: _handleItemDeleted
)
),
new Route(
name: '/meals/new',
builder: (navigator, route) => new MealFragment(
navigator: navigator,
onCreated: _handleItemCreated
)
),
new Route(
name: '/measurements/new',
builder: (navigator, route) => new MeasurementFragment(
navigator: navigator,
onCreated: _handleMeasurementCreated
onCreated: _handleItemCreated
)
),
new Route(
......@@ -54,16 +67,16 @@ class FitnessApp extends App {
}
}
void _handleMeasurementCreated(Measurement measurement) {
void _handleItemCreated(FitnessItem item) {
setState(() {
_userData.add(measurement);
_userData.add(item);
_userData.sort((a, b) => a.when.compareTo(b.when));
});
}
void _handleMeasurementDeleted(Measurement measurement) {
void _handleItemDeleted(FitnessItem item) {
setState(() {
_userData.remove(measurement);
_userData.remove(item);
});
}
......@@ -76,11 +89,6 @@ class FitnessApp extends App {
});
}
final List<Measurement> _userData = [
new Measurement(weight: 180.0, when: new DateTime.now().add(const Duration(days: -1))),
new Measurement(weight: 160.0, when: new DateTime.now()),
];
Widget build() {
return new Theme(
data: new ThemeData(
......
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:sky/painting/text_style.dart';
import 'package:sky/editing/input.dart';
import 'package:sky/widgets/basic.dart';
import 'package:sky/widgets/default_text_style.dart';
import 'package:sky/widgets/icon_button.dart';
import 'package:sky/widgets/ink_well.dart';
import 'package:sky/widgets/material.dart';
import 'package:sky/widgets/navigator.dart';
import 'package:sky/widgets/scaffold.dart';
import 'package:sky/widgets/scrollable_viewport.dart';
import 'package:sky/widgets/snack_bar.dart';
import 'package:sky/widgets/theme.dart';
import 'package:sky/widgets/tool_bar.dart';
import 'fitness_item.dart';
class Meal extends FitnessItem {
Meal({ DateTime when, this.description }) : super(when: when);
final String description;
}
class MealRow extends FitnessItemRow {
MealRow({ Meal meal, FitnessItemHandler onDismissed })
: super(item: meal, onDismissed: onDismissed);
Widget buildContent() {
Meal meal = item;
List<Widget> children = [
new Flexible(
child: new Text(
meal.description,
style: const TextStyle(textAlign: TextAlign.right)
)
),
new Flexible(
child: new Text(
meal.displayDate,
style: Theme.of(this).text.caption.copyWith(textAlign: TextAlign.right)
)
)
];
return new Flex(
children,
alignItems: FlexAlignItems.baseline,
textBaseline: DefaultTextStyle.of(this).textBaseline
);
}
}
class MealFragment extends StatefulComponent {
MealFragment({ this.navigator, this.onCreated });
Navigator navigator;
FitnessItemHandler onCreated;
void syncFields(MealFragment source) {
navigator = source.navigator;
onCreated = source.onCreated;
}
String _description = "";
void _handleSave() {
onCreated(new Meal(when: new DateTime.now(), description: _description));
navigator.pop();
}
Widget buildToolBar() {
return new ToolBar(
left: new IconButton(
icon: "navigation/close",
onPressed: navigator.pop),
center: new Text('New Meal'),
right: [new InkWell(
child: new Listener(
onGestureTap: (_) => _handleSave(),
child: new Text('SAVE')
)
)]
);
}
void _handleDescriptionChanged(String description) {
setState(() {
_description = description;
});
}
Widget buildBody() {
Meal meal = new Meal(when: new DateTime.now());
return new Material(
type: MaterialType.canvas,
child: new ScrollableViewport(
child: new Container(
padding: const EdgeDims.all(20.0),
child: new Block([
new Text(meal.displayDate),
new Input(
focused: false,
placeholder: 'Describe meal',
onChanged: _handleDescriptionChanged
),
])
)
)
);
}
Widget build() {
return new Scaffold(
toolbar: buildToolBar(),
body: buildBody()
);
}
}
......@@ -2,8 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:sky/painting/text_style.dart';
import 'package:sky/editing/input.dart';
import 'package:sky/widgets/basic.dart';
import 'package:sky/widgets/default_text_style.dart';
import 'package:sky/widgets/icon_button.dart';
import 'package:sky/widgets/ink_well.dart';
import 'package:sky/widgets/material.dart';
......@@ -11,19 +13,46 @@ import 'package:sky/widgets/navigator.dart';
import 'package:sky/widgets/scaffold.dart';
import 'package:sky/widgets/scrollable_viewport.dart';
import 'package:sky/widgets/snack_bar.dart';
import 'package:sky/widgets/theme.dart';
import 'package:sky/widgets/tool_bar.dart';
typedef void MeasurementHandler(Measurement measurement);
import 'fitness_item.dart';
class Measurement {
Measurement({ this.when, this.weight });
class Measurement extends FitnessItem {
Measurement({ DateTime when, this.weight }) : super(when: when);
final DateTime when;
final double weight;
// TODO(jackson): Internationalize
String get displayWeight => "${weight.toStringAsFixed(2)} lbs";
String get displayDate => "${when.year.toString()}-${when.month.toString().padLeft(2,'0')}-${when.day.toString().padLeft(2,'0')}";
}
class MeasurementRow extends FitnessItemRow {
MeasurementRow({ Measurement measurement, FitnessItemHandler onDismissed })
: super(item: measurement, onDismissed: onDismissed);
Widget buildContent() {
Measurement measurement = item;
List<Widget> children = [
new Flexible(
child: new Text(
measurement.displayWeight,
style: const TextStyle(textAlign: TextAlign.right)
)
),
new Flexible(
child: new Text(
measurement.displayDate,
style: Theme.of(this).text.caption.copyWith(textAlign: TextAlign.right)
)
)
];
return new Flex(
children,
alignItems: FlexAlignItems.baseline,
textBaseline: DefaultTextStyle.of(this).textBaseline
);
}
}
class MeasurementFragment extends StatefulComponent {
......@@ -31,7 +60,7 @@ class MeasurementFragment extends StatefulComponent {
MeasurementFragment({ this.navigator, this.onCreated });
Navigator navigator;
MeasurementHandler onCreated;
FitnessItemHandler onCreated;
void syncFields(MeasurementFragment source) {
navigator = source.navigator;
......@@ -76,7 +105,7 @@ class MeasurementFragment extends StatefulComponent {
});
}
Widget buildMeasurementPane() {
Widget buildBody() {
Measurement measurement = new Measurement(when: new DateTime.now());
return new Material(
type: MaterialType.canvas,
......@@ -105,7 +134,7 @@ class MeasurementFragment extends StatefulComponent {
Widget build() {
return new Scaffold(
toolbar: buildToolBar(),
body: buildMeasurementPane(),
body: buildBody(),
snackBar: buildSnackBar()
);
}
......
......@@ -27,8 +27,6 @@ class SettingsFragment extends Component {
final BackupMode backup;
final SettingsUpdater updater;
bool showModeDialog = false;
void _handleBackupChanged(bool value) {
if (updater != null)
updater(backup: value ? BackupMode.enabled : BackupMode.disabled);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment