├── .gitignore ├── .vscode ├── settings.json └── tasks.json ├── LICENSE ├── README.md ├── package.json ├── src ├── app │ ├── app.ts │ ├── common │ │ ├── Conversions.ts │ │ ├── UnitOfMeasureState.ts │ │ ├── UserProfile.ts │ │ ├── formulaBmi.ts │ │ ├── formulaBmr.ts │ │ └── formulaThr.ts │ ├── directives │ │ ├── customValidators.ts │ │ ├── formulas.ts │ │ ├── max.ts │ │ ├── min.ts │ │ └── profile.ts │ ├── pipes │ │ ├── BmiPipe.ts │ │ └── HeightPipe.ts │ └── templates │ │ ├── app.html │ │ ├── formulas.html │ │ └── userprofile.html ├── index.html ├── main.css └── tsconfig.json ├── tsd.json └── typings ├── angular2 └── angular2.d.ts └── tsd.d.ts /.gitignore: -------------------------------------------------------------------------------- 1 | .tmp 2 | .bat 3 | *.js 4 | *.js.map 5 | node_modules 6 | *~ 7 | .idea/ -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | // Place your settings in this file to overwrite default and user settings. 2 | { 3 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.1.0", 3 | "command": "npm", 4 | "windows": { 5 | "command": "npm.cmd" 6 | }, 7 | "tasks": [ 8 | { 9 | // Build task, Ctrl+Shift+B 10 | // "npm install --loglevel info" 11 | "taskName": "run-script", 12 | "isBuildCommand": true, 13 | "args": ["tsc"] 14 | }, 15 | { 16 | // "npm start" 17 | "taskName": "start", 18 | "args": [] 19 | } 20 | ] 21 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Jeremy Likness 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Angular 2 Health App 2 | 3 | [Angular 1.x Health App](https://github.com/JeremyLikness/AngularHealthApp) Ported to AngularJS 2.0 (alpha) to learn the new Angular and understand pain points of migration. Read the [Angular migration](http://ivision.com/blog/changes-angular-2-migration-case-study/) blog post for analysis and commentary. 4 | 5 | 1. Navigate to the parent folder you would like to put the project in. 6 | 2. `git clone https://github.com/JeremyLikness/Angular2HealthApp.git` 7 | 3. `cd Angular2HealthApp` 8 | 4. `npm install` 9 | 5. `npm run-script tsc` 10 | 6. `npm start` 11 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Angular2HealthApp", 3 | "version": "1.0.0", 4 | "description": "Port of AngularJS 1.x Health App to 2.0", 5 | "main": "index.js", 6 | "scripts": { 7 | "tsc" : "tsc -p src -w", 8 | "start" : "live-server --open=src" 9 | }, 10 | "keywords": [], 11 | "author": "Jeremy Likness", 12 | "license": "MIT", 13 | "devDependencies": { 14 | "live-server": "0.8.2", 15 | "typescript": "1.6.2" 16 | }, 17 | "repository": { 18 | "type" : "git", 19 | "url" : "https://github.com/JeremyLikness/Angular2HealthApp.git" 20 | }, 21 | "dependencies": { 22 | "angular2": "2.0.0-beta.0", 23 | "systemjs": "0.19.2", 24 | "reflect-metadata": "0.1.2", 25 | "es6-shim": "^0.33.3", 26 | "rxjs": "5.0.0-beta.0", 27 | "zone.js": "0.5.10" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/app/app.ts: -------------------------------------------------------------------------------- 1 | import {bootstrap} from 'angular2/platform/browser'; 2 | import {provide, Component} from 'angular2/core'; 3 | import {FORM_DIRECTIVES, ControlContainer} from 'angular2/common'; 4 | import {IUserProfile, UserProfile} from './common/UserProfile'; 5 | import {IUnitOfMeasureState, UnitOfMeasureState} from './common/UnitOfMeasureState'; 6 | import {IConversions, Conversions} from './common/Conversions'; 7 | import {ProfileComponent} from './directives/profile'; 8 | import {FormulaComponent} from './directives/formulas'; 9 | import {HealthAppCustomValidators} from './directives/customValidators'; 10 | 11 | let userProfileFactory = () => (new UserProfile()); 12 | let uomStateFactory = () => (new UnitOfMeasureState()); 13 | let conversionsFactory = () => (new Conversions()); 14 | 15 | @Component({ 16 | selector: 'my-app', 17 | templateUrl: 'app/templates/app.html', 18 | directives: [ProfileComponent, FormulaComponent] 19 | }) 20 | class AppComponent { } 21 | bootstrap(AppComponent, [provide("UserProfile", {useFactory:userProfileFactory}), 22 | provide("UnitOfMeasureState", {useFactory:uomStateFactory}), 23 | provide("Conversions", {useFactory:conversionsFactory}), 24 | provide(HealthAppCustomValidators, {useClass: HealthAppCustomValidators})]); -------------------------------------------------------------------------------- /src/app/common/Conversions.ts: -------------------------------------------------------------------------------- 1 | export interface IConversions { 2 | inchesToCentimeters: (inches: number) => number; 3 | inchesToFeet: (inches: number) => number; 4 | centimetersToInches: (centimeters: number) => number; 5 | poundsToKilograms: (pounds: number) => number; 6 | kilogramsToPounds: (kg: number) => number; 7 | } 8 | 9 | export var Conversions = (function () { 10 | 11 | var conversions = { 12 | centimetersPerInch: 2.54, 13 | inchesPerFoot: 12, 14 | poundsPerKilogram: 2.205 15 | }; 16 | 17 | function Constructor() { 18 | 19 | }; 20 | 21 | Constructor.prototype.inchesToCentimeters = function (inches) { 22 | var input = Number(inches); 23 | return input * conversions.centimetersPerInch; 24 | }; 25 | 26 | Constructor.prototype.inchesToFeet = function (inches) { 27 | var input = Number(inches); 28 | return input / conversions.inchesPerFoot; 29 | }; 30 | 31 | Constructor.prototype.centimetersToInches = function (centimeters) { 32 | var input = Number(centimeters); 33 | return input / conversions.centimetersPerInch; 34 | }; 35 | 36 | Constructor.prototype.poundsToKilograms = function (pounds) { 37 | var input = Number(pounds); 38 | return input / conversions.poundsPerKilogram; 39 | }; 40 | 41 | Constructor.prototype.kilogramsToPounds = function (kg) { 42 | var input = Number(kg); 43 | return input * conversions.poundsPerKilogram; 44 | }; 45 | 46 | return Constructor; 47 | 48 | })(); -------------------------------------------------------------------------------- /src/app/common/UnitOfMeasureState.ts: -------------------------------------------------------------------------------- 1 | export interface IUnitOfMeasureState { 2 | usMeasure: boolean; 3 | metricMeasure: boolean; 4 | toggle: () => void 5 | } 6 | 7 | export var UnitOfMeasureState: any = (function () { 8 | 9 | var usMeasure = true, metricMeasure = false; 10 | 11 | function Constructor() { 12 | } 13 | 14 | Constructor.prototype.toggle = function () { 15 | this.usMeasure = !this.usMeasure; 16 | } 17 | 18 | Object.defineProperty(Constructor.prototype, "usMeasure", { 19 | enumerable: true, 20 | configurable: false, 21 | get: function() { 22 | return usMeasure; 23 | }, 24 | set: function (val) { 25 | usMeasure = !!val; 26 | metricMeasure = !usMeasure; 27 | } 28 | }); 29 | 30 | Object.defineProperty(Constructor.prototype, "metricMeasure", { 31 | enumerable: true, 32 | configurable: false, 33 | get: function() { 34 | return metricMeasure; 35 | }, 36 | set: function (val) { 37 | metricMeasure = !!val; 38 | usMeasure = !metricMeasure; 39 | } 40 | }); 41 | 42 | return Constructor; 43 | 44 | })(); -------------------------------------------------------------------------------- /src/app/common/UserProfile.ts: -------------------------------------------------------------------------------- 1 | export interface IUserProfile { 2 | isMale: boolean; 3 | isFemale: boolean; 4 | heightInches: number; 5 | weightPounds: number; 6 | ageYears: number; 7 | toggleGender: () => void 8 | } 9 | 10 | export var UserProfile: any = (function () { 11 | 12 | var isMale = true, isFemale = false; 13 | 14 | function Constructor() { 15 | this.heightInches = 60; 16 | this.weightPounds = 130; 17 | this.ageYears = 40; 18 | } 19 | 20 | Constructor.prototype.toggleGender = function () { 21 | this.isMale = !this.isMale; 22 | }; 23 | 24 | Object.defineProperty(Constructor.prototype, "isMale", { 25 | enumerable: true, 26 | configurable: false, 27 | get: function() { 28 | return isMale; 29 | }, 30 | set: function (val) { 31 | isMale = !!val; 32 | isFemale = !isMale; 33 | } 34 | }); 35 | 36 | Object.defineProperty(Constructor.prototype, "isFemale", { 37 | enumerable: true, 38 | configurable: false, 39 | get: function() { 40 | return isFemale; 41 | }, 42 | set: function (val) { 43 | isFemale = !!val; 44 | isMale = !isFemale; 45 | } 46 | }); 47 | 48 | return Constructor; 49 | 50 | })(); -------------------------------------------------------------------------------- /src/app/common/formulaBmi.ts: -------------------------------------------------------------------------------- 1 | function formulaBmi (profile) { 2 | 3 | // BMI = (weight in pound * 703) / (height in inches)^2 4 | var bmi = (profile.weight * 703) / (profile.height * profile.height); 5 | 6 | // round it 7 | return Math.round(bmi * 10.0)/10.0; 8 | } 9 | 10 | export {formulaBmi} -------------------------------------------------------------------------------- /src/app/common/formulaBmr.ts: -------------------------------------------------------------------------------- 1 | function formulaBmr (profile) { 2 | 3 | // Women - 655 + (4.35 x weight in pounds) + (4.7 x height in inches) - (4.7 x age in years) 4 | function woman(weight, height, age) { 5 | return Math.floor(655 + (4.35 * weight) + (4.7 * height) - (4.7 * age)); 6 | } 7 | 8 | // Men - 66 + (6.23 x weight in pounds) + (12.7 x height in inches) - (6.8 x age in years ) 9 | function man(weight, height, age) { 10 | return Math.floor(66 + (6.23 * weight) + (12.7 * height) - (6.8 * age)); 11 | } 12 | 13 | return profile.isMale ? man(profile.weight, profile.height, profile.age) : 14 | woman(profile.weight, profile.height, profile.age); 15 | } 16 | 17 | export {formulaBmr} -------------------------------------------------------------------------------- /src/app/common/formulaThr.ts: -------------------------------------------------------------------------------- 1 | function formulaThr (age) { 2 | 3 | // max heart rate = 220 - age; 4 | var max = 220.0 - Number(age); 5 | 6 | // min range = 50% 7 | var min = Math.round(5.0 * max) / 10.0; 8 | 9 | // max range = 85% 10 | var maxRate = Math.round(8.5 * max) / 10.0; 11 | 12 | return { 13 | min: min, 14 | max: maxRate 15 | }; 16 | } 17 | 18 | export {formulaThr} -------------------------------------------------------------------------------- /src/app/directives/customValidators.ts: -------------------------------------------------------------------------------- 1 | import {Control} from "angular2/common"; 2 | 3 | export class HealthAppCustomValidators { 4 | 5 | static min(min: number): Function { 6 | return (control: Control): {[key: string]: any} => { 7 | var v: number = Number(control.value); 8 | return v < min || isNaN(v) ? 9 | {"min": {"requiredMin": min, "actualMin": v}} : 10 | null; 11 | }; 12 | } 13 | 14 | static max(max: number): Function { 15 | return (control: Control): {[key: string]: any} => { 16 | var v: number = Number(control.value); 17 | return v > max || isNaN(v) ? 18 | {"max": {"requiredMax": max, "actualMax": v}} : 19 | null; 20 | }; 21 | } 22 | } -------------------------------------------------------------------------------- /src/app/directives/formulas.ts: -------------------------------------------------------------------------------- 1 | import {Inject, Component} from 'angular2/core'; 2 | import {IUserProfile} from '../common/UserProfile'; 3 | import {BmiPipe} from '../pipes/BmiPipe'; 4 | import {formulaBmr} from '../common/formulaBmr'; 5 | import {formulaBmi} from '../common/formulaBmi'; 6 | import {formulaThr} from '../common/formulaThr'; 7 | 8 | interface IFormulaParameter { 9 | isMale: boolean; 10 | weight: number; 11 | height: number; 12 | age: number; 13 | } 14 | 15 | @Component({ 16 | selector: 'formulas', 17 | templateUrl: 'app/templates/formulas.html', 18 | pipes: [BmiPipe] 19 | }) 20 | export class FormulaComponent { 21 | constructor(@Inject("UserProfile")private userProfile: IUserProfile) {} 22 | 23 | private profileToParam(): IFormulaParameter { 24 | return { 25 | isMale: this.userProfile.isMale, 26 | weight: this.userProfile.weightPounds, 27 | height: this.userProfile.heightInches, 28 | age: this.userProfile.ageYears 29 | }; 30 | } 31 | 32 | public get bmr(): number { 33 | return formulaBmr(this.profileToParam()); 34 | } 35 | 36 | public get bmi(): number { 37 | return formulaBmi(this.profileToParam()); 38 | } 39 | 40 | public get thr(): any { 41 | return formulaThr(this.userProfile.ageYears); 42 | } 43 | } -------------------------------------------------------------------------------- /src/app/directives/max.ts: -------------------------------------------------------------------------------- 1 | import {Attribute, Directive, forwardRef, Provider} from "angular2/core"; 2 | import {Control, NG_VALIDATORS} from 'angular2/common'; 3 | import {HealthAppCustomValidators} from "./customValidators"; 4 | 5 | const MAX_VALIDATOR = new Provider(NG_VALIDATORS, {useExisting: 6 | forwardRef(() => MaxValidator), multi:true}); 7 | 8 | @Directive({ 9 | selector: '[max][ngControl],[max][ngFormControl],[max][ngModel]', 10 | providers: [MAX_VALIDATOR] 11 | }) 12 | export class MaxValidator { 13 | 14 | private _validator: Function; 15 | private _max: number; 16 | 17 | constructor(@Attribute("max") max: string) { 18 | this._validator = HealthAppCustomValidators.max(this._max); 19 | } 20 | 21 | validate(c: Control): {[key: string]: any} { 22 | return this._validator(c); 23 | } 24 | } -------------------------------------------------------------------------------- /src/app/directives/min.ts: -------------------------------------------------------------------------------- 1 | import {Attribute, Directive, forwardRef, Provider} from "angular2/core"; 2 | import {Control, NG_VALIDATORS} from 'angular2/common'; 3 | import {HealthAppCustomValidators} from "./customValidators"; 4 | 5 | const MIN_VALIDATOR = new Provider(NG_VALIDATORS, {useExisting: 6 | forwardRef(() => MinValidator), multi:true}); 7 | 8 | @Directive({ 9 | selector: '[min][ngControl],[min][ngFormControl],[min][ngModel]', 10 | providers: [MIN_VALIDATOR] 11 | }) 12 | export class MinValidator { 13 | 14 | private _validator: Function; 15 | 16 | constructor(@Attribute("min") min: string) { 17 | this._validator = HealthAppCustomValidators.min(Number(min)); 18 | } 19 | validate(c: Control): {[key: string]: any} { 20 | return this._validator(c); 21 | } 22 | } -------------------------------------------------------------------------------- /src/app/directives/profile.ts: -------------------------------------------------------------------------------- 1 | import {Control, ControlGroup, FORM_DIRECTIVES, FormBuilder} from 'angular2/common'; 2 | import {Inject, Component} from 'angular2/core'; 3 | import {IUserProfile} from '../common/UserProfile'; 4 | import {IUnitOfMeasureState} from '../common/UnitOfMeasureState'; 5 | import {IConversions} from '../common/Conversions'; 6 | import {HeightPipe} from '../pipes/HeightPipe'; 7 | import {MinValidator} from '../directives/min'; 8 | import {MaxValidator} from '../directives/max'; 9 | 10 | @Component({ 11 | selector: 'user-profile', 12 | templateUrl: 'app/templates/userprofile.html', 13 | directives: [FORM_DIRECTIVES, MinValidator, MaxValidator], 14 | pipes: [HeightPipe] 15 | }) 16 | export class ProfileComponent { 17 | constructor(@Inject("UserProfile")private userProfile: IUserProfile, 18 | @Inject("UnitOfMeasureState")private unitOfMeasureState: IUnitOfMeasureState, 19 | @Inject("Conversions")private conversions: IConversions) { 20 | // set up weight value 21 | this._weightValue = unitOfMeasureState.usMeasure ? userProfile.weightPounds : 22 | conversions.poundsToKilograms(userProfile.weightPounds); 23 | this._wasMetric = unitOfMeasureState.metricMeasure; 24 | 25 | // set up weight validations 26 | var fb = new FormBuilder(), that = this; 27 | this.myForm = fb.group({ 28 | weight: [this.weightValue, (c: Control) => that.weightValidator(that, c)] 29 | }); 30 | 31 | // set up age 32 | this._ageValue = userProfile.ageYears; 33 | } 34 | 35 | private weightValidator(that: ProfileComponent, c: Control): any { 36 | var weight: number; 37 | if (c.value === null || isNaN(c.value)) { 38 | return { 39 | required: true 40 | }; 41 | } 42 | weight = Number(c.value); 43 | if (isNaN(weight) || weight < that.minWeight || weight > that.maxWeight) { 44 | return { 45 | weightRange: true 46 | }; 47 | } 48 | return null; 49 | } 50 | 51 | private _ageValue: number; 52 | 53 | private _weightValue: number; 54 | 55 | private _wasMetric: boolean; 56 | 57 | public myForm: ControlGroup; 58 | 59 | public get uomLabel(): string { 60 | return this.unitOfMeasureState.usMeasure ? "Imperial" : "Metric"; 61 | } 62 | 63 | public get genderLabel(): string { 64 | return this.userProfile.isMale ? "Male" : "Female"; 65 | } 66 | 67 | public get minHeight(): number { 68 | return this.unitOfMeasureState.usMeasure ? 24 : 60; 69 | } 70 | 71 | public get maxHeight(): number { 72 | return this.unitOfMeasureState.usMeasure ? 84: 215; 73 | } 74 | 75 | public get heightValue(): number { 76 | return this.unitOfMeasureState.usMeasure ? 77 | this.userProfile.heightInches : 78 | this.conversions.inchesToCentimeters(this.userProfile.heightInches); 79 | } 80 | 81 | public set heightValue(val: number) { 82 | this.userProfile.heightInches = this.unitOfMeasureState.usMeasure ? val 83 | : this.conversions.centimetersToInches(val); 84 | } 85 | 86 | public get minWeight(): number { 87 | return this.unitOfMeasureState.usMeasure ? 20 : 9; 88 | } 89 | 90 | public get maxWeight(): number { 91 | return this.unitOfMeasureState.usMeasure ? 400 : 182; 92 | } 93 | 94 | public get weightUom(): string { 95 | return this.unitOfMeasureState.usMeasure ? "lbs" : "kg"; 96 | } 97 | 98 | public get weightValue(): number { 99 | if (this.unitOfMeasureState.metricMeasure !== this._wasMetric) { 100 | this._wasMetric = this.unitOfMeasureState.metricMeasure; 101 | if (this._wasMetric) { 102 | this._weightValue = Math.round(this.conversions.poundsToKilograms(this._weightValue)); 103 | } 104 | else { 105 | this._weightValue = Math.round(this.conversions.kilogramsToPounds(this._weightValue)); 106 | } 107 | } 108 | return this._weightValue; 109 | } 110 | 111 | public set weightValue(val: number) { 112 | var incoming: number = Number(val), adjustedWeight: number = incoming; 113 | this._weightValue = incoming; 114 | if (this.unitOfMeasureState.metricMeasure) { 115 | adjustedWeight = this.conversions.kilogramsToPounds(incoming); 116 | } 117 | if (adjustedWeight >= 20 && adjustedWeight <= 400) { 118 | this.userProfile.weightPounds = adjustedWeight; 119 | } 120 | } 121 | 122 | public get ageValue(): number { 123 | return this._ageValue; 124 | } 125 | 126 | public set ageValue(val: number) { 127 | var incoming = Number(val); 128 | this._ageValue = val; 129 | if (incoming >= 13 && incoming <= 120) { 130 | this.userProfile.ageYears = incoming; 131 | } 132 | } 133 | 134 | public toggleUom(): void { 135 | this.unitOfMeasureState.toggle(); 136 | } 137 | 138 | public toggleGender(): void { 139 | this.userProfile.toggleGender(); 140 | } 141 | } -------------------------------------------------------------------------------- /src/app/pipes/BmiPipe.ts: -------------------------------------------------------------------------------- 1 | import {Pipe, Inject} from 'angular2/core'; 2 | 3 | @Pipe({ 4 | name: 'bmi' 5 | }) 6 | export class BmiPipe { 7 | constructor() {} 8 | transform(input:number, args: string[]) : any { 9 | var value = Number(input); 10 | 11 | if (value >= 30.0) { 12 | return 'Obese'; 13 | } 14 | 15 | if (value >= 25.0) { 16 | return 'Overweight'; 17 | } 18 | 19 | if (value < 18.5) { 20 | return 'Underweight'; 21 | } 22 | 23 | return 'Normal'; 24 | } 25 | } -------------------------------------------------------------------------------- /src/app/pipes/HeightPipe.ts: -------------------------------------------------------------------------------- 1 | import {Pipe, Inject} from 'angular2/core'; 2 | import {IUnitOfMeasureState} from '../common/UnitOfMeasureState'; 3 | import {IConversions} from '../common/Conversions'; 4 | 5 | @Pipe({ 6 | name: 'height' 7 | }) 8 | export class HeightPipe { 9 | constructor( 10 | @Inject("UnitOfMeasureState")private unitOfMeasureState: IUnitOfMeasureState, 11 | @Inject("Conversions")private conversions: IConversions) {} 12 | transform(value:number, args: string[]) : any { 13 | var heightInches = Number(value), heightCentimeters, m, ft, result = '', 14 | convert = !!args[0]; 15 | if (this.unitOfMeasureState.usMeasure) { 16 | ft = Math.floor(this.conversions.inchesToFeet(heightInches)); 17 | if (ft > 0) { 18 | result = ft + " ft. "; 19 | } 20 | heightInches -= ft * 12; 21 | if (heightInches >= 1) { 22 | result += (Math.floor(heightInches) + ' in.'); 23 | } 24 | } 25 | else { 26 | if (convert !== undefined && !!convert === convert && !convert) { 27 | heightCentimeters = heightInches; 28 | } 29 | else { 30 | heightCentimeters = this.conversions.inchesToCentimeters(heightInches); 31 | } 32 | result = Math.round(heightCentimeters) + ' cm.'; 33 | } 34 | return result; 35 | } 36 | } -------------------------------------------------------------------------------- /src/app/templates/app.html: -------------------------------------------------------------------------------- 1 |

Angular 2 Health App

2 | 3 |
4 | -------------------------------------------------------------------------------- /src/app/templates/formulas.html: -------------------------------------------------------------------------------- 1 |
3 |

BMR:

4 |

{{bmr}} Calories

5 |
6 | 7 |
9 |

BMI:

10 |

{{bmi}}

11 |

{{bmi | bmi}}

12 |
13 | 14 |
15 |

THR (50% — 85%)

16 |

{{thr.min}} — {{thr.max}} BPM

17 |
-------------------------------------------------------------------------------- /src/app/templates/userprofile.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 |
5 |
Click to Toggle Unit of Measure
6 |
7 | 8 |
9 |
10 | 11 | 12 |
13 |
Click to Toggle Gender
14 |
15 | 16 |
17 |
18 | 19 | 20 |
21 |
Height:
22 |
23 | {{minHeight | height:false}} 24 | 29 | {{maxHeight | height:false}} 30 |
31 | {{userProfile.heightInches | height:true}} 32 |
33 |
34 | 35 | 36 |
37 |
Weight ({{minWeight}} - {{maxWeight}}):
38 |
39 | 45 | {{weightUom}}. 46 |
47 |
48 | 49 | 50 |
51 |
Age (13 - 120):
52 |
53 | years 61 |
62 |
63 | 64 |
65 | -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Angular 2 Health App 4 | 5 | 6 | 7 | 8 | 9 | 15 | 16 | 17 | loading... 18 | 19 | -------------------------------------------------------------------------------- /src/main.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: arial, verdana, sans-serif; 3 | line-height: 1.2em; 4 | } 5 | 6 | h1 { 7 | font-size: 2.0em; 8 | font-weight: bold; 9 | color: darkblue; 10 | } 11 | 12 | button { 13 | width: 60px; 14 | border-color: black; 15 | border-radius: 0px; 16 | border-style: solid; 17 | border-width: 2px; 18 | padding: 5px; 19 | } 20 | 21 | div.break { 22 | clear: both; 23 | } 24 | 25 | div.tile { 26 | width: 290px; 27 | height: 150px; 28 | float: left; 29 | margin: 5px; 30 | padding: 5px; 31 | background: lightblue; 32 | border: solid 2px darkblue; 33 | } 34 | 35 | div.unit { 36 | min-width: 200px; 37 | max-width: 310px; 38 | float: left; 39 | margin: 5px; 40 | padding: 5px; 41 | } 42 | 43 | div.Obese { 44 | background: red; 45 | } 46 | 47 | div.Overweight { 48 | background: lightcoral; 49 | } 50 | 51 | div.Underweight { 52 | background: lightcoral; 53 | } 54 | 55 | input.error { 56 | border: 2px solid red; 57 | } 58 | 59 | .label { 60 | max-width: 60%; 61 | float: left; 62 | font-weight: bold; 63 | text-align: right; 64 | padding-right: 5px; 65 | vertical-align: middle; 66 | } 67 | 68 | .labelTarget { 69 | float: left; 70 | text-align: left; 71 | vertical-align: middle; 72 | } -------------------------------------------------------------------------------- /src/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES5", 4 | "module": "commonjs", 5 | "sourceMap": true, 6 | "emitDecoratorMetadata": true, 7 | "experimentalDecorators": true, 8 | "removeComments": false, 9 | "noImplicitAny": false 10 | } 11 | } -------------------------------------------------------------------------------- /tsd.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "v4", 3 | "repo": "borisyankov/DefinitelyTyped", 4 | "ref": "master", 5 | "path": "typings", 6 | "bundle": "typings/tsd.d.ts", 7 | "installed": {} 8 | } 9 | -------------------------------------------------------------------------------- /typings/angular2/angular2.d.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for Angular 2 2 | // Project: http://angular.io/ 3 | // Definitions by: angular team 4 | // Definitions: https://github.com/borisyankov/DefinitelyTyped 5 | 6 | // Angular 2 distributes typings in our NPM package. 7 | // To get the typings, simply: 8 | // $ npm install angular2 9 | // and use TypeScript 1.6.2 or later. 10 | // 11 | // Note that TypeScript must be configured with 12 | // --moduleResolution node 13 | // which is the default when --module commonjs 14 | -------------------------------------------------------------------------------- /typings/tsd.d.ts: -------------------------------------------------------------------------------- 1 | 2 | --------------------------------------------------------------------------------