measurement.dart 5.36 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 33 34 35 36 37 38
}

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,
Eric Seidel's avatar
Eric Seidel committed
39
          style: Theme.of(this).text.subhead
40 41 42 43 44 45 46 47 48
        )
      ),
      new Flexible(
        child: new Text(
          measurement.displayDate,
          style: Theme.of(this).text.caption.copyWith(textAlign: TextAlign.right)
        )
      )
    ];
49
    return new Row(
50 51 52 53 54
      children,
      alignItems: FlexAlignItems.baseline,
      textBaseline: DefaultTextStyle.of(this).textBaseline
    );
  }
55 56
}

57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
class MeasurementDateDialog extends StatefulComponent {
  MeasurementDateDialog({ this.navigator, this.previousDate });

  Navigator navigator;
  DateTime previousDate;

  @override
  void initState() {
    _selectedDate = previousDate;
  }

  void syncConstructorArguments(MeasurementDateDialog source) {
    navigator = source.navigator;
    previousDate = source.previousDate;
  }

  DateTime _selectedDate;

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

  Widget build() {
    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'),
          onPressed: navigator.pop
        ),
        new FlatButton(
          child: new Text('OK'),
          onPressed: () {
            navigator.pop(_selectedDate);
          }
        ),
      ]
    );
  }
}

106 107 108 109 110
class MeasurementFragment extends StatefulComponent {

  MeasurementFragment({ this.navigator, this.onCreated });

  Navigator navigator;
111
  FitnessItemHandler onCreated;
112

113
  void syncConstructorArguments(MeasurementFragment source) {
114 115 116 117 118
    navigator = source.navigator;
    onCreated = source.onCreated;
  }

  String _weight = "";
119
  DateTime _when = new DateTime.now();
120 121
  String _errorMessage = null;

122
  void _handleSave() {
123 124 125
    double parsedWeight;
    try {
      parsedWeight = double.parse(_weight);
126 127
    } on FormatException catch(e) {
      print("Exception $e");
128 129 130 131
      setState(() {
        _errorMessage = "Save failed";
      });
    }
132
    onCreated(new Measurement(when: _when, weight: parsedWeight));
133 134 135 136 137 138 139 140 141 142
    navigator.pop();
  }

  Widget buildToolBar() {
    return new ToolBar(
      left: new IconButton(
        icon: "navigation/close",
        onPressed: navigator.pop),
      center: new Text('New Measurement'),
      right: [new InkWell(
143 144
        child: new GestureDetector(
          onTap: _handleSave,
145 146 147 148 149 150 151 152 153 154 155 156
          child: new Text('SAVE')
        )
      )]
    );
  }

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

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

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

171
  Widget buildBody() {
172 173
    Measurement measurement = new Measurement(when: _when);
    // TODO(jackson): Revisit the layout of this pane to be more maintainable
174 175
    return new Material(
      type: MaterialType.canvas,
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 185 186 187 188 189 190 191 192 193 194 195
            child: new Container(
              height: 50.0,
              child: new Column([
                new Text('Measurement Date'),
                new Text(measurement.displayDate, style: Theme.of(this).text.caption),
              ], alignItems: FlexAlignItems.start)
            )
          ),
          new Input(
            key: weightKey,
            placeholder: 'Enter weight',
            keyboardType: KeyboardType_NUMBER,
            onChanged: _handleWeightChanged
          ),
        ], alignItems: FlexAlignItems.stretch)
196 197 198 199 200 201 202
      )
    );
  }

  Widget buildSnackBar() {
    if (_errorMessage == null)
      return null;
203
    // TODO(jackson): This doesn't show up, unclear why.
204
    return new SnackBar(content: new Text(_errorMessage), showing: true);
205 206 207 208 209
  }

  Widget build() {
    return new Scaffold(
      toolbar: buildToolBar(),
210
      body: buildBody(),
211 212 213 214
      snackBar: buildSnackBar()
    );
  }
}