measurement.dart 5.54 KB
Newer Older
1 2 3 4
// 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.

5
part of fitness;
6

7 8
class Measurement extends FitnessItem {
  Measurement({ DateTime when, this.weight }) : super(when: when);
9
  Measurement.fromJson(Map json) : super.fromJson(json), weight = json['weight'];
10

11 12
  final double weight;

13
  // TODO(jackson): Internationalize
14
  String get displayWeight => "${weight.toStringAsFixed(1)} lbs";
15

16 17 18 19
  @override
  Map toJson() {
    Map json = super.toJson();
    json['weight'] = weight;
20
    json['type'] = runtimeType.toString();
21 22 23
    return json;
  }

24 25 26
  FitnessItemRow toRow({ FitnessItemHandler onDismissed }) {
    return new MeasurementRow(measurement: this, onDismissed: onDismissed);
  }
27 28 29 30 31 32
}

class MeasurementRow extends FitnessItemRow {
  MeasurementRow({ Measurement measurement, FitnessItemHandler onDismissed })
    : super(item: measurement, onDismissed: onDismissed);

33
  Widget buildContent(BuildContext context) {
34 35 36 37 38
    Measurement measurement = item;
    List<Widget> children = [
      new Flexible(
        child: new Text(
          measurement.displayWeight,
39
          style: Theme.of(context).text.subhead
40 41 42 43 44
        )
      ),
      new Flexible(
        child: new Text(
          measurement.displayDate,
45
          style: Theme.of(context).text.caption.copyWith(textAlign: TextAlign.right)
46 47 48
        )
      )
    ];
49
    return new Row(
50 51
      children,
      alignItems: FlexAlignItems.baseline,
52
      textBaseline: DefaultTextStyle.of(context).textBaseline
53 54
    );
  }
55 56
}

57 58 59
class MeasurementDateDialog extends StatefulComponent {
  MeasurementDateDialog({ this.navigator, this.previousDate });

60 61
  final NavigatorState navigator;
  final DateTime previousDate;
62

63 64 65 66
  MeasurementDateDialogState createState() => new MeasurementDateDialogState();
}

class MeasurementDateDialogState extends State<MeasurementDateDialog> {
67 68
  @override
  void initState() {
69
    _selectedDate = config.previousDate;
70 71 72 73 74 75 76 77 78 79
  }

  DateTime _selectedDate;

  void _handleDateChanged(DateTime value) {
    setState(() {
      _selectedDate = value;
    });
  }

80
  Widget build(BuildContext context) {
81 82 83 84 85 86 87 88 89 90 91
    return new Dialog(
      content: new DatePicker(
        selectedDate: _selectedDate,
        firstDate: new DateTime(2015, 8),
        lastDate: new DateTime(2101),
        onChanged: _handleDateChanged
      ),
      contentPadding: EdgeDims.zero,
      actions: [
        new FlatButton(
          child: new Text('CANCEL'),
92
          onPressed: config.navigator.pop
93 94 95 96
        ),
        new FlatButton(
          child: new Text('OK'),
          onPressed: () {
97
            config.navigator.pop(_selectedDate);
98 99 100 101 102 103 104
          }
        ),
      ]
    );
  }
}

105 106 107
class MeasurementFragment extends StatefulComponent {
  MeasurementFragment({ this.navigator, this.onCreated });

108 109
  final NavigatorState navigator;
  final FitnessItemHandler onCreated;
110

111 112
  MeasurementFragmentState createState() => new MeasurementFragmentState();
}
113

114
class MeasurementFragmentState extends State<MeasurementFragment> {
115 116
  final GlobalKey<PlaceholderState> _snackBarPlaceholderKey = new GlobalKey<PlaceholderState>();

117
  String _weight = "";
118
  DateTime _when = new DateTime.now();
119

120
  void _handleSave() {
121 122 123
    double parsedWeight;
    try {
      parsedWeight = double.parse(_weight);
124 125
    } on FormatException catch(e) {
      print("Exception $e");
126 127 128 129 130
      showSnackBar(
        navigator: config.navigator,
        placeholderKey: _snackBarPlaceholderKey,
        content: new Text('Save failed')
      );
131
    }
132 133
    config.onCreated(new Measurement(when: _when, weight: parsedWeight));
    config.navigator.pop();
134 135 136 137 138 139
  }

  Widget buildToolBar() {
    return new ToolBar(
      left: new IconButton(
        icon: "navigation/close",
140
        onPressed: config.navigator.pop),
141
      center: new Text('New Measurement'),
142 143 144
      right: [
        // TODO(abarth): Should this be a FlatButton?
        new InkWell(
145
          onTap: _handleSave,
146 147
          child: new Text('SAVE')
        )
148
      ]
149 150 151 152 153 154 155 156 157
    );
  }

  void _handleWeightChanged(String weight) {
    setState(() {
      _weight = weight;
    });
  }

158 159
  static final GlobalKey weightKey = new GlobalKey();

160
  void _handleDatePressed() {
161
    showDialog(config.navigator, (NavigatorState navigator) {
162 163 164 165 166 167 168 169 170 171
      return new MeasurementDateDialog(navigator: navigator, previousDate: _when);
    }).then((DateTime value) {
      if (value == null)
        return;
      setState(() {
        _when = value;
      });
    });
  }

172
  Widget buildBody(BuildContext context) {
173 174
    Measurement measurement = new Measurement(when: _when);
    // TODO(jackson): Revisit the layout of this pane to be more maintainable
175
    return new Material(
176 177 178
      child: new Container(
        padding: const EdgeDims.all(20.0),
        child: new Column([
179 180
          new GestureDetector(
            onTap: _handleDatePressed,
181 182 183 184
            child: new Container(
              height: 50.0,
              child: new Column([
                new Text('Measurement Date'),
185
                new Text(measurement.displayDate, style: Theme.of(context).text.caption),
186 187 188 189 190 191
              ], alignItems: FlexAlignItems.start)
            )
          ),
          new Input(
            key: weightKey,
            placeholder: 'Enter weight',
192
            keyboardType: KeyboardType.NUMBER,
193 194 195
            onChanged: _handleWeightChanged
          ),
        ], alignItems: FlexAlignItems.stretch)
196 197 198 199
      )
    );
  }

200
  Widget build(BuildContext context) {
201
    return new Scaffold(
Adam Barth's avatar
Adam Barth committed
202
      toolBar: buildToolBar(),
203
      body: buildBody(context),
204
      snackBar: new Placeholder(key: _snackBarPlaceholderKey)
205 206 207
    );
  }
}