From 15129c32c3d9337c1da8fb7b2740c37d9d979764 Mon Sep 17 00:00:00 2001
From: Dapeng <verydapeng@gmail.com>
Date: Tue, 20 Sep 2016 14:59:02 +0800
Subject: [PATCH] redesign owner details page

---
 .../samples/petclinic/model/Visit.java        |   3 +-
 .../petclinic/web/VisitController.java        |  99 ----------------
 .../samples/petclinic/web/VisitResource.java  |  61 ++++++++++
 src/main/webapp/index.html                    |   2 +-
 src/main/webapp/scripts/app/app.js            |  26 ++---
 .../webapp/scripts/app/fragments/nav.html     |   2 +-
 .../webapp/scripts/app/fragments/welcome.html |   4 +-
 .../owner-details/owner-details.template.html |  53 +++------
 .../scripts/app/owner-list/OwnerController.js | 110 ------------------
 .../scripts/app/owner-list/ownerDetail.html   |  75 ------------
 .../scripts/app/owner-list/ownerForm.html     |  45 -------
 .../app/owner-list/ownerSearchForm.html       |   9 --
 .../app/pet-form/pet-form.component.js        |   5 +-
 .../app/pet-form/pet-form.template.html       |   6 +-
 .../webapp/scripts/app/pet/PetController.js   |  62 ----------
 src/main/webapp/scripts/app/pet/petForm.html  |  38 ------
 .../scripts/app/visits/visits.component.js    |  34 ++++++
 .../scripts/app/visits/visits.template.html   |  27 +++++
 18 files changed, 162 insertions(+), 499 deletions(-)
 delete mode 100644 src/main/java/org/springframework/samples/petclinic/web/VisitController.java
 create mode 100644 src/main/java/org/springframework/samples/petclinic/web/VisitResource.java
 delete mode 100644 src/main/webapp/scripts/app/owner-list/OwnerController.js
 delete mode 100644 src/main/webapp/scripts/app/owner-list/ownerDetail.html
 delete mode 100644 src/main/webapp/scripts/app/owner-list/ownerForm.html
 delete mode 100644 src/main/webapp/scripts/app/owner-list/ownerSearchForm.html
 delete mode 100644 src/main/webapp/scripts/app/pet/PetController.js
 delete mode 100644 src/main/webapp/scripts/app/pet/petForm.html
 create mode 100644 src/main/webapp/scripts/app/visits/visits.component.js
 create mode 100644 src/main/webapp/scripts/app/visits/visits.template.html

diff --git a/src/main/java/org/springframework/samples/petclinic/model/Visit.java b/src/main/java/org/springframework/samples/petclinic/model/Visit.java
index a418c17a..004c836d 100644
--- a/src/main/java/org/springframework/samples/petclinic/model/Visit.java
+++ b/src/main/java/org/springframework/samples/petclinic/model/Visit.java
@@ -15,6 +15,7 @@
  */
 package org.springframework.samples.petclinic.model;
 
+import com.fasterxml.jackson.annotation.JsonFormat;
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import org.hibernate.validator.constraints.NotEmpty;
 import org.springframework.format.annotation.DateTimeFormat;
@@ -42,7 +43,7 @@ public class Visit extends BaseEntity {
      */
     @Column(name = "visit_date")
     @Temporal(TemporalType.TIMESTAMP)
-    @DateTimeFormat(pattern = "yyyy/MM/dd")
+    @JsonFormat(pattern = "yyyy-MM-dd")
     private Date date;
 
     /**
diff --git a/src/main/java/org/springframework/samples/petclinic/web/VisitController.java b/src/main/java/org/springframework/samples/petclinic/web/VisitController.java
deleted file mode 100644
index 705ed2b5..00000000
--- a/src/main/java/org/springframework/samples/petclinic/web/VisitController.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright 2002-2013 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.springframework.samples.petclinic.web;
-
-import java.util.Map;
-
-import javax.validation.Valid;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.samples.petclinic.model.Pet;
-import org.springframework.samples.petclinic.model.Visit;
-import org.springframework.samples.petclinic.service.ClinicService;
-import org.springframework.stereotype.Controller;
-import org.springframework.validation.BindingResult;
-import org.springframework.web.bind.WebDataBinder;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.InitBinder;
-import org.springframework.web.bind.annotation.ModelAttribute;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-
-/**
- * @author Juergen Hoeller
- * @author Ken Krebs
- * @author Arjen Poutsma
- * @author Michael Isvy
- */
-@Controller
-public class VisitController {
-
-    private final ClinicService clinicService;
-
-
-    @Autowired
-    public VisitController(ClinicService clinicService) {
-        this.clinicService = clinicService;
-    }
-
-    @InitBinder
-    public void setAllowedFields(WebDataBinder dataBinder) {
-        dataBinder.setDisallowedFields("id");
-    }
-    
-    /**
-     *  Called before each and every @RequestMapping annotated method.
-     *  2 goals:
-     *  - Make sure we always have fresh data
-     *  - Since we do not use the session scope, make sure that Pet object always has an id 
-     *    (Even though id is not part of the form fields)
-     * @param petId
-     * @return Pet
-     */
-    @ModelAttribute("visit")
-    public Visit loadPetWithVisit(@PathVariable("petId") int petId) {
-        Pet pet = this.clinicService.findPetById(petId);
-        Visit visit = new Visit();
-        pet.addVisit(visit);  
-        return visit;
-    }
-
-	// Spring MVC calls method loadPetWithVisit(...) before initNewVisitForm is called
-    @GetMapping("/owners/*/pets/{petId}/visits/new")
-    public String initNewVisitForm(@PathVariable("petId") int petId, Map<String, Object> model) {
-        return "pets/createOrUpdateVisitForm";
-    }
-
-	// Spring MVC calls method loadPetWithVisit(...) before processNewVisitForm is called
-    @PostMapping("/owners/{ownerId}/pets/{petId}/visits/new")
-    public String processNewVisitForm(@Valid Visit visit, BindingResult result) {
-        if (result.hasErrors()) {
-            return "pets/createOrUpdateVisitForm";
-        } else {
-            this.clinicService.saveVisit(visit);
-            return "redirect:/owners/{ownerId}";
-        }
-    }
-
-    @GetMapping("/owners/*/pets/{petId}/visits")
-    public String showVisits(@PathVariable int petId, Map<String, Object> model) {
-        model.put("visits", this.clinicService.findPetById(petId).getVisits());
-        return "visitList";
-    }
-
-}
diff --git a/src/main/java/org/springframework/samples/petclinic/web/VisitResource.java b/src/main/java/org/springframework/samples/petclinic/web/VisitResource.java
new file mode 100644
index 00000000..68798f79
--- /dev/null
+++ b/src/main/java/org/springframework/samples/petclinic/web/VisitResource.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2002-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.samples.petclinic.web;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.samples.petclinic.model.Visit;
+import org.springframework.samples.petclinic.service.ClinicService;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.validation.Valid;
+
+/**
+ * @author Juergen Hoeller
+ * @author Ken Krebs
+ * @author Arjen Poutsma
+ * @author Michael Isvy
+ */
+@RestController
+public class VisitResource {
+
+    private final ClinicService clinicService;
+
+    @Autowired
+    public VisitResource(ClinicService clinicService) {
+        this.clinicService = clinicService;
+    }
+
+    @PostMapping("/owners/{ownerId}/pets/{petId}/visits")
+    @ResponseStatus(HttpStatus.NO_CONTENT)
+    public void create(
+            @Valid @RequestBody Visit visit,
+            @PathVariable("petId") int petId) {
+
+        clinicService.findPetById(petId).addVisit(visit);
+        clinicService.saveVisit(visit);
+    }
+
+    @GetMapping("/owners/{ownerId}/pets/{petId}/visits")
+    public Object visits(@PathVariable("petId") int petId) {
+        return clinicService.findPetById(petId).getVisits();
+    }
+}
diff --git a/src/main/webapp/index.html b/src/main/webapp/index.html
index 63775e3c..874e05b4 100644
--- a/src/main/webapp/index.html
+++ b/src/main/webapp/index.html
@@ -12,13 +12,13 @@
 
     <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js"></script>
     <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular-route.min.js"></script>
-    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular-resource.min.js"></script>
 
     <script src="scripts/app/app.js"></script>
     <script src="scripts/app/owner-list/owner-list.component.js"></script>
     <script src="scripts/app/owner-details/owner-details.component.js"></script>
     <script src="scripts/app/owner-form/owner-form.component.js"></script>
     <script src="scripts/app/pet-form/pet-form.component.js"></script>
+    <script src="scripts/app/visits/visits.component.js"></script>
     <script src="scripts/app/vet-list/vet-list.component.js"></script>
 
 </head>
diff --git a/src/main/webapp/scripts/app/app.js b/src/main/webapp/scripts/app/app.js
index b9245802..66007615 100644
--- a/src/main/webapp/scripts/app/app.js
+++ b/src/main/webapp/scripts/app/app.js
@@ -2,7 +2,7 @@
 /* App Module */
 var petClinicApp = angular.module('petClinicApp', [
     'ngRoute', 'layoutNav', 'layoutFooter', 'layoutWelcome',
-    'ownerList', 'ownerDetails', 'ownerForm','petForm', 'vetList']);
+    'ownerList', 'ownerDetails', 'ownerForm', 'petForm', 'visits', 'vetList']);
 
 petClinicApp.config(['$locationProvider', '$routeProvider', function ($locationProvider, $routeProvider) {
 
@@ -22,26 +22,18 @@ petClinicApp.config(['$locationProvider', '$routeProvider', function ($locationP
         template: '<pet-form></pet-form>'
     }).when('/owners/:ownerId/pets/:petId', {
         template: '<pet-form></pet-form>'
+    }).when('/owners/:ownerId/pets/:petId/visits', {
+        template: '<visits></visits>'
     }).when('/vets', {
         template: '<vet-list></vet-list>'
     }).otherwise('/welcome');
 
 }]);
 
-angular.module('layoutWelcome', []);
-
-angular.module("layoutWelcome").component("layoutWelcome", {
-    templateUrl: "scripts/app/fragments/welcome.html"
-});
-
-angular.module('layoutNav', []);
-
-angular.module("layoutNav").component("layoutNav", {
-    templateUrl: "scripts/app/fragments/nav.html"
-});
-
-angular.module('layoutFooter', []);
-
-angular.module("layoutFooter").component("layoutFooter", {
-    templateUrl: "scripts/app/fragments/footer.html"
+['welcome', 'nav', 'footer'].forEach(function(c) {
+    var mod = 'layout' + c.toUpperCase().substring(0, 1) + c.substring(1);
+    angular.module(mod, []);
+    angular.module(mod).component(mod, {
+        templateUrl: "scripts/app/fragments/" + c + ".html"
+    });
 });
\ No newline at end of file
diff --git a/src/main/webapp/scripts/app/fragments/nav.html b/src/main/webapp/scripts/app/fragments/nav.html
index f6722423..7dd8cded 100644
--- a/src/main/webapp/scripts/app/fragments/nav.html
+++ b/src/main/webapp/scripts/app/fragments/nav.html
@@ -19,7 +19,7 @@
                     <a href="javascript:void(0)" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Owners <span class="caret"></span></a>
                     <ul class="dropdown-menu">
                         <li><a href="#!/owners">All</a></li>
-                        <li><a href="#!/new-owner">New</a></li>
+                        <li><a href="#!/new-owner">Register</a></li>
                     </ul>
                 </li>
 
diff --git a/src/main/webapp/scripts/app/fragments/welcome.html b/src/main/webapp/scripts/app/fragments/welcome.html
index a91aa92e..8ff4bbe0 100644
--- a/src/main/webapp/scripts/app/fragments/welcome.html
+++ b/src/main/webapp/scripts/app/fragments/welcome.html
@@ -1 +1,3 @@
- <p>Welcome to Petclinic  </p>
+ <h1>Welcome to Petclinic</h1>
+
+ <img src="resources/images/pets.png" alt="pets logo" />
\ No newline at end of file
diff --git a/src/main/webapp/scripts/app/owner-details/owner-details.template.html b/src/main/webapp/scripts/app/owner-details/owner-details.template.html
index 293ce831..78220f5d 100644
--- a/src/main/webapp/scripts/app/owner-details/owner-details.template.html
+++ b/src/main/webapp/scripts/app/owner-details/owner-details.template.html
@@ -29,41 +29,22 @@
 
 <h2>Pets and Visits</h2>
 
-<table class="table" style="width:600px;">
-    <tr ng-repeat="pet in $ctrl.owner.pets">
-        <td valign="top" style="width: 120px;">
-            <dl class="dl-horizontal">
-                <dt>Name</dt>
-                <dd>{{pet.name}}</dd>
-                <dt>Birth Date</dt>
-                <dd>{{pet.birthDate | date:'MM/dd/yyyy'}}</dd>
-                <dt>Type</dt>
-                <dd>{{pet.type.name}}</dd>
-            </dl>
-        </td>
-        <td valign="top">
-            <table class="table-condensed">
-                <thead>
-                <tr>
-                    <th>Visit Date</th>
-                    <th>Description</th>
-                </tr>
-                </thead>
-                <tr ng-repeat="visit in pet.visits">
-                    <td>{{visit.date | date:'MM/dd/yyyy'}}</td>
-                    <td>{{visit.description}}</td>
-                </tr>
-                <tr>
-                    <td>
-                        <a href="#!/owners/{{$ctrl.owner.id}}/pets/{{pet.id}}">Edit Pet</a>
-                    </td>
-                    <td>
-                        <a href="...">Add Visit</a>
-                    </td>
-                </tr>
-            </table>
-        </td>
-    </tr>
-</table>
+<div ng-repeat="pet in $ctrl.owner.pets">
+    <h3>{{pet.name}}</h3>
+    <p>
+        {{pet.birthDate | date:'yyyy MMM dd'}} - {{pet.type.name}}
+    </p>
+    <h4>Visits</h4>
+    <p style="margin-left: 2em;" ng-repeat="visit in pet.visits">
+        <span style="font-style: italic; margin-right: 1em;">{{visit.date | date:'yyyy MMM dd'}}</span>
+        {{visit.description}}
+    </p>
+
+    <p style="margin-left: 2em;" ng-if="pet.visits.length == 0">
+        No visit yet
+    </p>
+
+    <hr/>
+</div>
 
 
diff --git a/src/main/webapp/scripts/app/owner-list/OwnerController.js b/src/main/webapp/scripts/app/owner-list/OwnerController.js
deleted file mode 100644
index 6f2cddc0..00000000
--- a/src/main/webapp/scripts/app/owner-list/OwnerController.js
+++ /dev/null
@@ -1,110 +0,0 @@
-'use strict';
-
-function loadOwner($scope, $resource, $stateParams) {
-	var ownerResource = $resource('/petclinic/owner/' + $stateParams.id);
-	$scope.owner =  ownerResource.get();
-}
-
-/*
- * Owner Search
- */
-angular.module('controllers').controller('ownerSearchController', ['$scope', '$state',
-                                                            function($scope, $state) {
-
-	$scope.ownerSearchForm = {};
-	// form always needs to be initialised
-	// otherwise we can't read $scope.ownerSearchForm.lastName
-
-	$scope.submitOwnerSearchForm = function() {
-		var lastNameValue;
-		$state.go('app.ownerlist', {lastName: $scope.ownerSearchForm.lastName});
-}}]);
-
-/*
- * Owners List
- */
-angular.module('controllers').controller('ownerListController', ['$scope', '$resource', '$stateParams',
-             function($scope, $resource, $stateParams) {
-
-	var destUrl = '/petclinic/owner/list?lastName=';
-	if(angular.isDefined($stateParams.lastName)) {
-		destUrl += $stateParams.lastName;
-	}
-    var ownerResource = $resource(destUrl);
-    $scope.ownerList = ownerResource.query();
-}]);
-
-/*
- * Owners detail (used for both Editable and non-editable pages)
- */
-angular.module('controllers').controller('ownerDetailController', ['$scope', '$resource', '$stateParams',
-               loadOwner
-]);
-
-
-
-/*
- * Form used to create and edit owners
- */
-angular.module('controllers').controller('ownerFormController', ['$scope', '$http', '$resource', '$stateParams', '$state',
-function($scope, $http, $resource, $stateParams, $state) {
-
-	$scope.submitOwnerForm = {};
-
-	$scope.submitOwnerForm = function() {
-		var form = $scope.owner;
-
-		// Creating a Javascript object
-		var data = {
-				firstName:	form.firstName,
-				lastName: 	form.lastName,
-				address: 	form.address,
-				city: 		form.city,
-				telephone:	form.telephone
-		};
-
-        var request;
-
-        if ($state.current.name == 'app.owneredit') {
-            var restUrl = "/petclinic/owner/" + $stateParams.id;
-            request = $http.put(restUrl, data);
-        } else { // in case of owner creation
-            var restUrl = "/petclinic/owner";
-            request = $http.post(restUrl, data);
-        }
-
-        request.then(function () {
-            $state.go('app.ownerlist');
-        }, function (response) {
-            var error = response.data;
-            alert(error.error + "\r\n" + error.errors.map(function (e) {
-                    return e.field + ": " + e.defaultMessage;
-                }).join("\r\n"));
-        });
-
-	}
-
-	if ($state.current.name == 'app.owneredit') {
-		loadOwner($scope, $resource, $stateParams);
-	}
-
-}]);
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/main/webapp/scripts/app/owner-list/ownerDetail.html b/src/main/webapp/scripts/app/owner-list/ownerDetail.html
deleted file mode 100644
index 45a7b9fd..00000000
--- a/src/main/webapp/scripts/app/owner-list/ownerDetail.html
+++ /dev/null
@@ -1,75 +0,0 @@
-<div class="container">
-
-    <h2>Owner Information</h2>
-
-    <table class="table table-striped" style="width:600px;">
-        <tr>
-            <th>Name</th>
-            <td><b>{{owner.firstName}} {{owner.lastName}}</b></td>
-        </tr>
-        <tr>
-            <th>Address</th>
-            <td>{{owner.address}}</td>
-        </tr>
-        <tr>
-            <th>City</th>
-            <td>{{owner.city}}</td>
-        </tr>
-        <tr>
-            <th>Telephone</th>
-            <td>{{owner.telephone}}</td>
-        </tr>
-         <tr>
-            <td> 
-                <a class="btn btn-info" ui-sref="app.owneredit({id: owner.id})">Edit Owner</a></td>
-            <td>
-                <a ui-sref="app.petcreate({ownerid: owner.id})"  class="btn btn-success">Add New Pet</a>
-                </td>
-        </tr>
-    </table>
-
-    <h2>Pets and Visits</h2>
-
-        <table class="table" style="width:600px;">
-            <tr ng-repeat="pet in owner.pets">
-                <td valign="top" style="width: 120px;">
-                    <dl class="dl-horizontal">
-                        <dt>Name</dt>
-                        <dd>{{pet.name}}</dd>
-                        <dt>Birth Date</dt>
-                        <dd>{{pet.birthDate | date:'MM/dd/yyyy'}}</dd>
-                        <dt>Type</dt>
-                        <dd>{{pet.type.name}}</dd>
-                    </dl>
-                </td>
-                <td valign="top">
-                    <table class="table-condensed">
-                        <thead>
-                        <tr>
-                            <th>Visit Date</th>
-                            <th>Description</th>
-                        </tr>
-                        </thead>
-                            <tr ng-repeat="visit in pet.visits">
-                                <td>{{visit.date | date:'MM/dd/yyyy'}}</td>
-                                <td>{{visit.description}}</td>
-                            </tr>
-                        <tr>
-                            <td> 
-			                    <a ui-sref="app.petedit( {ownerid: owner.id, petid: pet.id})">Edit Pet</a>
-			                </td>
-                            <td>
-			                    <spring:url value="/owners/{ownerId}/pets/{petId}/visits/new" var="visitUrl">
-			                        <spring:param name="ownerId" value="${owner.id}"/>
-			                        <spring:param name="petId" value="${pet.id}"/>
-			                    </spring:url>
-			                    <a href="${fn:escapeXml(visitUrl)}">Add Visit</a>
-                            </td>
-                       	</tr>
-                    </table>
-                </td>
-            </tr>
-        </table>
-
-
-</div>
diff --git a/src/main/webapp/scripts/app/owner-list/ownerForm.html b/src/main/webapp/scripts/app/owner-list/ownerForm.html
deleted file mode 100644
index 38177f54..00000000
--- a/src/main/webapp/scripts/app/owner-list/ownerForm.html
+++ /dev/null
@@ -1,45 +0,0 @@
-<div class="container">
-    <h2>Owner</h2>
-    <form class="form-horizontal" name="ownerForm" data-ng-controller="ownerFormController">
-        <div class="form-group">
-            <label class="col-sm-2 control-label">First name</label>
-            <div class="col-sm-4">
-                <input class="form-control" ng-model="owner.firstName" name="firstName" required/>
-                <span ng-show="ownerForm.firstName.$error.required" class="help-inline">First name is required.</span>
-            </div>
-        </div>
-        <div class="form-group">
-            <label class="col-sm-2 control-label">Last name</label>
-            <div class="col-sm-4">
-                <input class="form-control" ng-model="owner.lastName" name="lastName" required/>
-                <span ng-show="ownerForm.lastName.$error.required" class="help-inline">Last name is required.</span>
-            </div>
-        </div>
-        <div class="form-group">
-            <label class="col-sm-2 control-label">Address</label>
-            <div class="col-sm-4">
-                <input class="form-control" ng-model="owner.address" name="address" required/>
-                <span ng-show="ownerForm.address.$error.required" class="help-inline">Address is required.</span>
-            </div>
-        </div>
-        <div class="form-group">
-            <label class="col-sm-2 control-label">City</label>
-            <div class="col-sm-4">
-                <input class="form-control" ng-model="owner.city" name="city" required/>
-                <span ng-show="ownerForm.city.$error.required" class="help-inline">City is required.</span>
-            </div>
-        </div>
-        <div class="form-group">
-            <label class="col-sm-2 control-label">Telephone</label>
-            <div class="col-sm-4">
-                <input class="form-control" ng-model="owner.telephone" name="telephone" required/>
-                <span ng-show="ownerForm.telephone.$error.required" class="help-inline">Telephone is required.</span>
-            </div>
-        </div>
-        <div class="form-group">
-            <div class="col-sm-offset-2 col-sm-4">
-                <button class="btn btn-primary" type="submit" ng-click="submitOwnerForm()">Submit</button>
-            </div>
-        </div>
-    </form>
-</div>
diff --git a/src/main/webapp/scripts/app/owner-list/ownerSearchForm.html b/src/main/webapp/scripts/app/owner-list/ownerSearchForm.html
deleted file mode 100644
index 4cd2fac2..00000000
--- a/src/main/webapp/scripts/app/owner-list/ownerSearchForm.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<h2>Owners</h2>
-<form class="form-inline" ng-controller="ownerSearchController">
-    <div class="control-group">
-        <label class="control-label">Last name</label>
-        <input class="form-control" type="text" ng-model="ownerSearchForm.lastName" size="30" maxlength="80"/>
-        <button class="btn btn-info" type="submit" ng-click="submitOwnerSearchForm()">Find Owners</button> |
-        <a class="btn btn-info" ui-sref="app.ownercreate">Add New Owner</a>
-    </div>
-</form>
\ No newline at end of file
diff --git a/src/main/webapp/scripts/app/pet-form/pet-form.component.js b/src/main/webapp/scripts/app/pet-form/pet-form.component.js
index 36b766ba..3de2b735 100644
--- a/src/main/webapp/scripts/app/pet-form/pet-form.component.js
+++ b/src/main/webapp/scripts/app/pet-form/pet-form.component.js
@@ -16,9 +16,10 @@ angular.module("petForm").component("petForm", {
 
             var petId = $routeParams.petId || 0;
 
-            if (petId) {
+            if (petId) { // edit
                 $http.get("owner/" + ownerId + "/pet/" + petId).then(function(resp) {
                     self.pet = resp.data;
+                    self.pet.birthDate = new Date(self.pet.birthDate);
                     self.petTypeId = "" + self.pet.type.id;
                 });
             } else {
@@ -26,6 +27,7 @@ angular.module("petForm").component("petForm", {
                     self.pet = {
                         owner: resp.data.firstName + " " + resp.data.lastName
                     };
+                    self.petTypeId = "1";
                 })
 
             }
@@ -54,6 +56,7 @@ angular.module("petForm").component("petForm", {
                 $location.url("owners/" + ownerId);
             }, function (response) {
                 var error = response.data;
+                error.errors = error.errors || [];
                 alert(error.error + "\r\n" + error.errors.map(function (e) {
                         return e.field + ": " + e.defaultMessage;
                     }).join("\r\n"));
diff --git a/src/main/webapp/scripts/app/pet-form/pet-form.template.html b/src/main/webapp/scripts/app/pet-form/pet-form.template.html
index 8811960a..a502b8eb 100644
--- a/src/main/webapp/scripts/app/pet-form/pet-form.template.html
+++ b/src/main/webapp/scripts/app/pet-form/pet-form.template.html
@@ -1,6 +1,6 @@
 <h2>Pet</h2>
 
-<form class="form-horizontal">
+<form class="form-horizontal" ng-submit="$ctrl.submit()">
     <div class="form-group">
         <label class="col-sm-2 control-label">Owner</label>
         <div class="col-sm-6">
@@ -19,7 +19,7 @@
     <div class="form-group">
         <label class="col-sm-2 control-label">Birth date</label>
         <div class="col-sm-6">
-            <input class="form-control" ng-model="$ctrl.pet.birthDate" value="{{pet.birthDate}}" required type="text"/>
+            <input class="form-control" ng-model="$ctrl.pet.birthDate" required type="date"/>
             <span ng-show="petForm.name.$error.required" class="help-inline"> birth date is required.</span>
         </div>
     </div>
@@ -35,7 +35,7 @@
 
     <div class="form-group">
         <div class="col-sm-6 col-sm-offset-2">
-            <button class="btn btn-primary" type="submit" ng-click="$ctrl.submit()">
+            <button class="btn btn-primary" type="submit">
                 Submit
             </button>
         </div>
diff --git a/src/main/webapp/scripts/app/pet/PetController.js b/src/main/webapp/scripts/app/pet/PetController.js
deleted file mode 100644
index a454a444..00000000
--- a/src/main/webapp/scripts/app/pet/PetController.js
+++ /dev/null
@@ -1,62 +0,0 @@
-'use strict';
-
-function loadPet($scope, $resource, $stateParams) {
-	var petResource = $resource('/petclinic/owner/' + $stateParams.ownerid +"/pet/" + $stateParams.petid);
-	$scope.pet =  petResource.get();
-	$scope.types = $resource("/petclinic/petTypes").query();
-}
-
-/*
- * Form used to create and edit pets
- */
-angular.module('controllers').controller('petFormController', ['$scope', '$http', '$resource', '$stateParams', '$state',
-function($scope, $http, $resource, $stateParams, $state) {
-	
-	$scope.submitPetForm = {};
-	
-	$scope.submitPetForm = function() {
-		var form = $scope.pet;
-		
-		// Creating a Javascript object
-		var data = {
-				name:		form.name,
-				birthDate: 	form.birthDate,
-				type: 		form.type
-		};
-		
-		if ($state.current.name == 'app.petedit') {
-			var restUrl = "/petclinic/owner/" + $stateParams.ownerid +"/pet/" +$stateParams.petid;
-			$http.put(restUrl, data);
-			$state.go('app.ownerdetail');			
-		}
-		else { // in case of pet creation
-			var restUrl = "/petclinic/owner/" + $stateParams.ownerid +"/pet";
-			$http.post(restUrl, data);
-			$state.go('app.ownerdetail');						
-		}
-	}
-	
-	if ($state.current.name == 'app.petedit') {
-		loadPet($scope, $resource, $stateParams);
-	}
-
-}]);
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/main/webapp/scripts/app/pet/petForm.html b/src/main/webapp/scripts/app/pet/petForm.html
deleted file mode 100644
index a1a09073..00000000
--- a/src/main/webapp/scripts/app/pet/petForm.html
+++ /dev/null
@@ -1,38 +0,0 @@
-<div class="container">
-
-    <h2>Pet</h2>
-
-    <form class="form-horizontal" name="petForm" data-ng-controller="petFormController">
-        <div class="form-group">
-            <label class="col-sm-2 control-label">Owner</label>
-            <div class="col-sm-6">
-                <p class="form-control-static">{{pet.owner}}</p>
-            </div>
-        </div>
-
-        <div class="form-group">
-            <label class="col-sm-2 control-label">Name </label>
-            <div class="col-sm-6">
-                <input class="form-control col-sm-4" ng-model="pet.name" name="name" required type="text"/>
-                <span ng-show="petForm.name.$error.required" class="help-inline"> Name is required.</span>
-            </div>
-        </div>
-
-        <div class="form-group">
-            <label class="col-sm-2 control-label">Birth date </label>
-            <div class="col-sm-6">
-                <input class="form-control" ng-model="pet.birthDate" value="{{pet.birthDate}}" required type="text"/>
-                <span ng-show="petForm.name.$error.required" class="help-inline"> birth date is required.</span>
-            </div>
-        </div>
-
-        <div class="form-group">
-            <label class="col-sm-2 control-label">Type </label>
-            <div class="col-sm-6">
-                <select class="form-control" ng-model="pet.type.id">
-                    <option ng-repeat="x in types" value="{{x.id}}">{{x.name}}</option>
-                </select>
-            </div>
-        </div>
-    </form>
-</div>
diff --git a/src/main/webapp/scripts/app/visits/visits.component.js b/src/main/webapp/scripts/app/visits/visits.component.js
new file mode 100644
index 00000000..706b4823
--- /dev/null
+++ b/src/main/webapp/scripts/app/visits/visits.component.js
@@ -0,0 +1,34 @@
+'use strict';
+
+angular.module('visits', [
+    'ngRoute'
+]);
+
+angular.module("visits").component("visits", {
+    templateUrl: "/petclinic/scripts/app/visits/visits.template.html",
+    controller: ["$http", '$routeParams', '$location', '$filter', function ($http, $routeParams, $location, $filter) {
+        var self = this;
+        var petId = $routeParams.petId || 0;
+        var url = "owners/" + ($routeParams.ownerId || 0) + "/pets/" + petId + "/visits";
+        self.date = new Date();
+        self.desc = "";
+
+        $http.get(url).then(function(resp) {
+            self.visits = resp.data;
+        });
+
+        self.submit = function() {
+
+            var data = {
+                date : $filter('date')(self.date, "yyyy-MM-dd"),
+                description : self.desc
+            };
+            console.log(data);
+            $http.post(url, data).then(function() {
+                $location.url("owners/" + $routeParams.ownerId);
+            }, function() {
+
+            });
+        };
+    }]
+});
\ No newline at end of file
diff --git a/src/main/webapp/scripts/app/visits/visits.template.html b/src/main/webapp/scripts/app/visits/visits.template.html
new file mode 100644
index 00000000..fa27dad2
--- /dev/null
+++ b/src/main/webapp/scripts/app/visits/visits.template.html
@@ -0,0 +1,27 @@
+<h2>Visits</h2>
+
+<form ng-submit="$ctrl.submit()">
+
+    <div class="form-group">
+        <label>Date</label>
+        <input type="date" class="form-control" ng-model='$ctrl.date'/>
+    </div>
+
+    <div class="form-group">
+        <label>Description</label>
+        <textarea class="form-control" ng-model="$ctrl.desc" style="resize:vertical;" required></textarea>
+    </div>
+
+    <div class="form-group">
+        <button class="btn btn-primary" type="submit">Add New Visit</button>
+    </div>
+
+</form>
+
+<h3>Previous Visits</h3>
+<table class="table table-striped">
+    <tr ng-repeat="v in $ctrl.visits">
+        <td class="col-sm-2">{{v.date}}</td>
+        <td>{{v.description}}</td>
+    </tr>
+</table>
\ No newline at end of file
-- 
GitLab