<!DOCTYPE html>
<html>

  <head>
    <base href="." />
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
    
    <script type="text/javascript" charset="utf-8">
      window.AngularVersionForThisPlunker = 'latest'
    </script>
    <title>angular playground</title>
    <link rel="stylesheet" href="style.css" />
    <script src="https://unpkg.com/core-js@2.4.1/client/shim.min.js"></script>
    <script src="https://unpkg.com/zone.js/dist/zone.js"></script>
    <script src="https://unpkg.com/zone.js/dist/long-stack-trace-zone.js"></script>
    <script src="https://unpkg.com/reflect-metadata@0.1.3/Reflect.js"></script>
    <script src="https://unpkg.com/systemjs@0.19.31/dist/system.js"></script>
    <script src="config.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
    <script>
    System.import('app')
      .catch(console.error.bind(console));
  </script>
  </head>

  <body>
    <my-app>
    loading...
  </my-app>
  </body>

</html>
//our root app component
import {Component, NgModule} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import {FormsModule} from '@angular/forms';
import {OrderComponent} from 'src/components/order/order';
import {ItemDetails} from 'src/components/item-details/item-details';

@Component({
  selector: 'my-app',
  template: `
    <div>
      <order></order>
    </div>
  `,
})
export class App {
  constructor() {}
}

@NgModule({
  imports: [ BrowserModule, FormsModule ],
  declarations: [ App,OrderComponent,ItemDetails ],
  bootstrap: [ App ]
})
export class AppModule {}
<div>
	<div class="jumbotron-n">
	  <h3>Order Processing System</h3>
    <div class="notification">
      <div class="activeItem" *ngIf="order.status!=='Processed'">Currently processing Order # {{order.id}}</div>
      <div class="success" *ngIf="order.status==='Processed'">Order Processed</div>
    </div>
    <div class="row">
      <div class="col-xs-5 info-col">
        <div class="col-xs-5 info-label">Order #</div>
        <div class="col-xs-7 info-value">{{order.id}}</div>
      </div>
      <div class="col-xs-7 info-col">
        <div class="col-xs-5 info-label">Order Date</div>
        <div class="col-xs-7 info-value">{{order.date}}</div>
      </div>
    </div>
    
    
    <div class="orderitems" style="padding-bottom:5px;">
      <h5> Order Items</h5>
      <ul class="list-group">
        <li class="list-group-item" 
            [class.active]="item.status==='In Process'" 
            *ngFor="let item of order.items">
          <span class="glyphicon glyphicon-ok" aria-hidden="true" *ngIf="item.status==='Processed'"></span>
          <span class="badge">{{ item.quantity }}</span>
          {{ item.name }}
        </li>
      </ul>
    </div>
    
    <div class="orderitems" style="padding-bottom:0">
      <button type="button" class="btn btn-success"  (click)="processNextOrCompleteOrder()">Start Processing Order Items</button>
    </div>
	</div> 
	
	
	<div class="itemDetailsContainer">
    <item-details [item]="itemSelected" *ngIf="itemSelected"
          [notifyItemProcessed]="processOrderItems" ></item-details>
  </div>
  
  
  
</div>
import {Component, ChangeDetectorRef} from '@angular/core';
import {Orders} from 'src/data/orders';
import {ItemDetails} from 'src/components/item-details/item-details';

@Component({
  selector: 'order',
  templateUrl: 'src/components/order/order.html',
})
export class OrderComponent {
    order: any;
    itemSelected: any;

    constructor(private cdRef:ChangeDetectorRef){
        this.order = Orders[0];
    }
    
    onItemSelect(item){
      this.itemSelected=item;
    }
    
    processNextOrCompleteOrder = () => {

      let pendingItems = this.order.items.filter((item) => item.status === 'Not Processed' );
      // get next item in the order
      if (pendingItems.length > 0) {
        this.itemSelected = pendingItems[0];
        this.cdRef.detectChanges();
        
      } else {
        this.itemSelected = null;
        this.cdRef.detectChanges();
        this.completeOrder();
      } 
    }
    
    processOrderItems = () => {
      this.itemSelected.status = "Processed";
      this.processNextOrCompleteOrder();
    }
    
    completeOrder = () => this.order.status = "Processed";
}
//main entry point
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
import {AppModule} from './app';

platformBrowserDynamic().bootstrapModule(AppModule);
export const Orders = [
  {
    id: 'A123',
    date: '10/02/2017',
    status: 'Not Processed',
    customer:{
      id: '010-28891',
      name: 'Sunrise Group'
    }
    items: [
      { 
        id: '001', 
        name: 'BetterHome Extra Soft Down Filled Pillow', 
        quantity: 2, 
        unitPrice: 6.12, 
        upc: 123456, 
        status: 'Not Processed' 
      },
      { 
        id: '002', 
        name: 'Vaga Sportswear SPORT BAG', 
        quantity: 1, 
        unitPrice: 14.99, 
        upc: 123457, 
        status: 'Not Processed' 
      },
      {
        id: '003',
        name: 'Rekor Quick Charge 3.0 39W Dual USB Wall Charger',
        quantity: 2,
        unitPrice: 17.69,
        upc: 123458,
        status: 'Not Processed'
      }
    ]
  }

];
System.config({
  //use typescript for compilation
  transpiler: 'typescript',
  //typescript compiler options
  typescriptOptions: {
    emitDecoratorMetadata: true
  },
  paths: {
    'npm:': 'https://unpkg.com/'
  },
  //map tells the System loader where to look for things
  map: {
    
    'app': './src',
    
    '@angular/core': 'npm:@angular/core/bundles/core.umd.js',
    '@angular/common': 'npm:@angular/common/bundles/common.umd.js',
    '@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
    '@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
    '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
    '@angular/http': 'npm:@angular/http/bundles/http.umd.js',
    '@angular/router': 'npm:@angular/router/bundles/router.umd.js',
    '@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
    
    '@angular/core/testing': 'npm:@angular/core/bundles/core-testing.umd.js',
    '@angular/common/testing': 'npm:@angular/common/bundles/common-testing.umd.js',
    '@angular/compiler/testing': 'npm:@angular/compiler/bundles/compiler-testing.umd.js',
    '@angular/platform-browser/testing': 'npm:@angular/platform-browser/bundles/platform-browser-testing.umd.js',
    '@angular/platform-browser-dynamic/testing': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic-testing.umd.js',
    '@angular/http/testing': 'npm:@angular/http/bundles/http-testing.umd.js',
    '@angular/router/testing': 'npm:@angular/router/bundles/router-testing.umd.js',
    
    'rxjs': 'npm:rxjs',
    'typescript': 'npm:typescript@2.0.2/lib/typescript.js'
  },
  //packages defines our app package
  packages: {
    app: {
      main: './main.ts',
      defaultExtension: 'ts'
    },
    rxjs: {
      defaultExtension: 'js'
    }
  }
});

.jumbotron-n{
  background-color: #aaa;
}
.info-label{
  background-color: #aaa;
  padding: 15px;
  border-right:1px solid #999;
}

.info-value{
  background-color: #ccc;
  padding: 15px;
}

.info-label-val{
  background-color: #ddd;
  padding: 15px;
  border:1px solid #999;
}


.info-value-i{
  background-color: #ccc;
  padding: 8px;
}


.info-col{
  padding: 0 30px;
}

.notification{
  padding: 5px 5px 15px 5px; 
}

.notification .activeItem{
    padding: 5px; 
    background: #fabf2d; 
    color: #202020;
}

.notification .success{
    padding: 2px; 
    background: #33FF86; 
    color: #202020;
}

.orderitems{
  padding: 5px 20px; 
}

.itemDetailsContainer{
  padding: 20px; 
  background-color: #aaa;
}
.itemDetails{
  padding: 10px 20px; 
  border: 2px solid #ccc;
  border-radius:10px;
}

.info-col-d .info-label, .info-col-d .info-value{
  border-bottom: 1px solid #333;
}

.div-button {
  text-align: center;
  margin 0 auto;
  background-color: #333;
  color:#ccc;
  border-radius:10px;
  padding: 10px;
}

.app-alert-danger{
  text-align: left;
  margin 0 auto;
  color:#ff9999;
  padding: 2px;
  background-color: #ffe6e6;
}

.div-row-10{
  padding: 10px 0;
}



<div class="itemDetails">
  <h4> Selected Item : {{item.name}} </h4>
  
  <div class="row">
      <div class="col-xs-12 info-col-d">
        <div class="col-xs-3 info-label-val">Product # {{item.id}}</div>
        <div class="col-xs-3 info-label-val">Quantity: {{item.quantity || ' '}}</div>
        <div class="col-xs-3 info-label-val">Unit Price ${{item.unitPrice || ' '}}</div>
        <div class="col-xs-3 info-label-val">UPC {{item.upc}}</div>
      </div>
  </div>

    
  <div class="row" style="padding-top:10px;">
    <div class="col-xs-6 info-label"><span id="item-barcode-label">Enter Scanned UPC #</span></div>
    <div class="col-xs-6 info-value-i">
      <input type="text" class="form-control" id="item-barcode" 
              [(ngModel)]="scannedUPC"
              aria-describedby="item-barcode-label">
    </div>
  </div>
  <div class="row" style="padding-top:10px;">
    <div class="col-xs-6 info-label">
      <span id="item-quantity-label">Quantity to be added to supply Cart</span>
    </div>
    <div class="col-xs-6 info-value-i">
      <input type="number" class="form-control" id="item-quantity"  name="item-quantity"
        aria-describedby="item-quantity-label" [(ngModel)]="suppliedQuantity">
    </div>
  </div>
  
   <div class="row" style="padding-top:10px;">
    <div class="col-xs-12">
      <div class="div-button" (click)="processItem()">Process Item</div>
    </div>
    
  </div>
  <div class="div-row-10">
     <div class="app-alert-danger"  *ngFor="let err of errors" >{{err}}</div>
  </div>
  
  
 

</div>
import {Component,Input, OnChanges, SimpleChanges, SimpleChange} from '@angular/core';

@Component({
  selector: 'item-details',
  templateUrl: 'src/components/item-details/item-details.html',
})
export class ItemDetails implements OnChanges {
  
  private _item;
  get item(): any {
    return this._item;
  }
  
  @Input()
  set item(val: any) {
    console.log('previous item = ', this._item);
    console.log('currently selected item=', val);
    this._item = val;
    this._item.status = 'In Process';
  }
  
  @Input() notifyItemProcessed: () => void;
  
  
  
  
  suppliedQuantity: number;
  scannedUPC: string;
  errors: string[];
  
  constructor(){
    this.suppliedQuantity = 0;
    this.scannedUPC = '';
  }
  
  ngOnChanges(changes: SimpleChanges) {
    console.log('inside ngOnChanges', changes);
    const currentItem: SimpleChange = changes.item;
    console.log('prev value: ', currentItem.previousValue);
    console.log('got item: ', currentItem.currentValue);
    if(currentItem.currentValue){
      this.scannedUPC = changes.item.currentValue.upc;
    }
    this.suppliedQuantity = 0;
    
  }
  
  processItem = () => {
    this.errors = [];
    if(this.suppliedQuantity < 1){
     this.errors.push('Supplied quantity cannot be less than 0');
    } 
   
    if(this.suppliedQuantity > this.item.quantity){
     this.errors.push('Supplied quantity cannot be more than ordered qunatity');
    }  
   
    if(this.scannedUPC != this.item.upc){
     this.errors.push('ScannedUPC not matching with product UPC');
    }  
   
    if (this.errors.length > 0){
     return false;
    }
    
    if (!this.item.quantityInCart){
     this.item['quantityInCart'] = this.suppliedQuantity;
    }
    this.suppliedQuantity = 0;
    this.scannedUPC = '';
    this.notifyItemProcessed();
    
    
  }
}