Skip to content

Commit

Permalink
feat(VIST-CPC-927): implementing aggregation and details page (#579)
Browse files Browse the repository at this point in the history
JIRA:[ link to jira
ticket](https://champlainsaintlambert.atlassian.net/browse/CPC-927)
## Context:
Visits only had access to the petId and vetId. By aggregating it, we now
have access to the needed vet information and pet information. There was
also no details page for our visits. The user only had access to the
general view which is a list.
This also allows us to populate a details page with a single get method.
## Changes

-Changed visitResponseDTO to now have the vet's full name and contact
information as well as the pet's birth date and name.
-Added navigation to Details Page
-Added Details Page to the front-end

UI CHANGES:

**BEFORE:**


![image](https://github.com/cgerard321/champlain_petclinic/assets/92550620/b21ea8dd-876d-41b1-ae55-c9509b01ffde)

**AFTER:**


![image](https://github.com/cgerard321/champlain_petclinic/assets/92550620/d61f8f3a-fe15-480e-aa19-c2faf76429de)

DETAILS PAGE:

![image](https://github.com/cgerard321/champlain_petclinic/assets/92550620/5c98e72e-54ad-456a-a1d9-0791c04520ad)
  • Loading branch information
CrisWillCarry authored Oct 23, 2023
1 parent db3f4bc commit bda738f
Show file tree
Hide file tree
Showing 20 changed files with 843 additions and 224 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,25 @@
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;
import java.util.Date;

@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class VisitResponseDTO {
private String visitId;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm")
private LocalDateTime visitDate;

@JsonFormat(pattern = "yyyy-MM-dd HH:mm")
private LocalDateTime visitDate;
private String description;
private String petId;
private String petName;
private Date petBirthDate;
private String practitionerId;
private String vetFirstName;
private String vetLastName;
private String vetEmail;
private String vetPhoneNumber;
private Status status;
}
4 changes: 4 additions & 0 deletions api-gateway/src/main/resources/static/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@
<script src="scripts/pet-form/pet-form.controller.js"></script>
<script src="scripts/pet-form/pet-form.component.js"></script>

<script src="scripts/visit-details-info/visit.js"></script>
<script src="scripts/visit-details-info/visit.controller.js"></script>
<script src="scripts/visit-details-info/visit.component.js"></script>

<script src="scripts/visits/visits.js"></script>
<script src="scripts/visits/visits.controller.js"></script>
<script src="scripts/visits/visits.component.js"></script>
Expand Down
2 changes: 1 addition & 1 deletion api-gateway/src/main/resources/static/scripts/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const whiteList = new Set([
/* App Module */
const petClinicApp = angular.module('petClinicApp', [
'ui.router', 'layoutNav', 'layoutFooter', 'layoutWelcome', 'ownerList', 'ownerDetails', 'ownerForm', 'ownerRegister', 'petRegister', 'petForm'
, 'visits', 'vetList','vetForm','vetDetails', 'visitList', 'billForm', 'billUpdateForm', 'loginForm', 'rolesDetails', 'signupForm', 'productDetailsInfo',
, 'visits', 'visit', 'visitList' , 'vetList','vetForm','vetDetails', 'billForm', 'billUpdateForm', 'loginForm', 'rolesDetails', 'signupForm', 'productDetailsInfo',
'billDetails', 'billsByOwnerId', 'billHistory','billsByVetId','inventoryList', 'inventoryForm', 'productForm','inventoryProductList', 'inventoryUpdateForm', 'productUpdateForm',
'verification' , 'adminPanel','resetPwdForm','forgotPwdForm','petTypeList', 'petDetails','userDetails']);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
'use strict';

angular.module('visit')
.component('visit', {
templateUrl: 'scripts/visit-details-info/visit.details.template.html',
controller: 'VisitController'
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
angular.module('visit')
.controller('VisitController', ['$http', '$stateParams', function ($http, $stateParams){
var self = this;

$http.get('api/gateway/visits/' + $stateParams.visitId).then(function (resp) {
self.visit = resp.data;
});


}])
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<link crossorigin="anonymous" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"
integrity="sha384-KyZXEAg3QhqLMpG8r+8fhAXLRk2vvoC2f3B09zVXn8CA5QIVfZOJ3BCsw2P0p/We" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">

<div class="container mt-5">
<div class="row">
<div class="col-md-6">
<a class="btn btn-success" href="http://localhost:8080/#!/visitList">Back to Visits</a>
</div>
</div>
<br>
<div class="alert alert-danger" ng-if="$ctrl.visit.status === 'CANCELLED'">
NOTICE: This visit is cancelled.
</div>
<br>
<div class="row">
<div class="col-md-4 text-start">
<h1 class="visit-title">VISIT(<span ng-style="{'color': $ctrl.visit.status === 'CANCELLED' ? 'red' : $ctrl.visit.status === 'UPCOMING' ? 'blue' : $ctrl.visit.status === 'CONFIRMED' ? 'green' : 'black'}">{{$ctrl.visit.status}}</span>)</h1>
</div>
<div class="col-md-4"></div> <!-- Empty column for spacing -->
<div class="col-md-4 text-end">
<h3 class="visit-id">Visit ID: {{$ctrl.visit.visitId}}</h3>
<h5>Date: {{$ctrl.visit.visitDate}}</h5>
</div>
<div class="col-md-4 text-start">
<h5>Visit Description: {{$ctrl.visit.description}}</h5>
</div>
</div>
<hr>
<div class="row g-5">
<div class="col-md-6">
<h3 class="text-center">Pet Information</h3>
<h5>Pet ID: {{$ctrl.visit.petId}}</h5>
<h5>Pet Name: {{$ctrl.visit.petName}} </h5>
<h5>Birth Date: {{$ctrl.visit.petBirthDate | date: 'yyyy-MM-dd'}}</h5>
<hr>
<h3 class="text-center">Vet Information</h3>
<h5>Vet ID: {{$ctrl.visit.practitionerId}}</h5>
<h5>Vet Name: {{$ctrl.visit.vetFirstName}} {{$ctrl.visit.vetLastName}} </h5>
<h5>Email: {{$ctrl.visit.vetEmail}}</h5>
<h5>Phone Number: {{$ctrl.visit.vetPhoneNumber}}</h5>
</div>
</div>
</div>

<style>
.visit-title, .visit-id {
font-size: 24px;
font-weight: bold;
}
</style>

<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js"></script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
'use strict';

angular.module('visit', ['ui.router'])
.config(['$stateProvider', function ($stateProvider) {
$stateProvider
.state('visitDetails', {
parent: 'app',
url: '/visit/:visitId/details',
template: '<visit></visit>'
});
}]);
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,12 @@ <h3 style="margin: 0; display: inline-block;">Upcoming Visits</h3>
<td class="border"></td>
<td class="border"></td>
<td class="border"></td>
<td class="border"></td>
</tr>

<!-- <tr id="visitId" ng-repeat="v in $ctrl.upcomingVisits | filter:search:$ctrl.query track by v.visitId" data-table-name="upcomingVisits">-->
<tr id="upcomingVisitId" ng-repeat="v in $ctrl.upcomingVisits | orderBy:propertyName:reverse | filter:search:$ctrl.query track by v.visitId" data-table-name="upcomingVisits">
<td class="border">{{v.visitId}}</td>
<td class="border"><a ui-sref="visitDetails({ visitId: v.visitId })"> {{ v.visitId }}</a></td>
<td class="border">{{v.visitDate | date:'yyyy-MM-ddTHH:mm:ss'}}</td>
<td class="border" style="white-space: pre-line">{{v.description}}</td>
<!-- <td style="white-space: pre-line">{{$ctrl.getPractitionerName(v.practitionerId)}}</td>-->
Expand Down Expand Up @@ -165,7 +166,7 @@ <h3 style="margin: 0; display: inline-block;">Confirmed Visits</h3>
<tbody id="confirmedTable">

<tr id="confirmedVisitId" ng-repeat="v in $ctrl.confirmedVisits | orderBy:propertyName:reverse | filter:search:$ctrl.query track by v.visitId" data-table-name="confirmedVisits">
<td class="border">{{v.visitId}}</td>
<td class="border"><a ui-sref="visitDetails({ visitId: v.visitId })"> {{ v.visitId }}</a></td>
<td class="border">{{v.visitDate | date:'yyyy-MM-ddTHH:mm:ss'}}</td>
<td class="border" style="white-space: pre-line">{{v.description}}</td>
<!-- <td style="white-space: pre-line">{{$ctrl.getPractitionerName(v.practitionerId)}}</td>-->
Expand Down Expand Up @@ -227,7 +228,7 @@ <h3 style="margin: 0; display: inline-block;">Cancelled Visits</h3>
<tbody id="cancelledTable">

<tr id="cancelledVisitId" ng-repeat="v in $ctrl.cancelledVisits | orderBy:propertyName:reverse | filter:search:$ctrl.query track by v.visitId" data-table-name="cancelledVisits">
<td class="border">{{v.visitId}}</td>
<td class="border"><a ui-sref="visitDetails({ visitId: v.visitId })"> {{ v.visitId }}</a></td>
<td class="border">{{v.visitDate | date:'yyyy-MM-ddTHH:mm:ss'}}</td>
<td class="border" style="white-space: pre-line">{{v.description}}</td>
<!-- <td style="white-space: pre-line">{{$ctrl.getPractitionerName(v.practitionerId)}}</td>-->
Expand Down Expand Up @@ -288,7 +289,7 @@ <h3 style="margin: 0; display: inline-block;">Completed Visits</h3>
<tbody id="completedTable">

<tr id="completedVisitId" ng-repeat="v in $ctrl.completedVisits | orderBy:propertyName:reverse | filter:search:$ctrl.query track by v.visitId" data-table-name="completedVisits">
<td class="border">{{v.visitId}}</td>
<td class="border"><a ui-sref="visitDetails({ visitId: v.visitId })"> {{ v.visitId }}</a></td>
<td class="border">{{v.visitDate | date:'yyyy-MM-ddTHH:mm:ss'}}</td>
<td class="border" style="white-space: pre-line">{{v.description}}</td>
<!-- <td style="white-space: pre-line">{{$ctrl.getPractitionerName(v.practitionerId)}}</td>-->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import java.io.IOException;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.Date;
import java.util.Objects;
import java.util.UUID;
import static org.junit.jupiter.api.Assertions.*;
Expand Down Expand Up @@ -63,8 +64,34 @@ static void tearDown() throws IOException {

@Test
void getAllVisits() throws JsonProcessingException {
VisitResponseDTO visitResponseDTO = new VisitResponseDTO("73b5c112-5703-4fb7-b7bc-ac8186811ae1", LocalDateTime.parse("2024-11-25 13:45", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")), "this is a dummy description", "2", "2", Status.UPCOMING);
VisitResponseDTO visitResponseDTO2 = new VisitResponseDTO("73b5c112-5703-4fb7-b7bc-ac8186811ae1", LocalDateTime.parse("2024-11-25 13:45", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")), "this is a dummy description", "2", "2", Status.UPCOMING);
VisitResponseDTO visitResponseDTO = VisitResponseDTO.builder()
.visitId("73b5c112-5703-4fb7-b7bc-ac8186811ae1")
.visitDate(LocalDateTime.parse("2024-11-25 13:45", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")))
.description("this is a dummy description")
.petId("2")
.petName("YourPetNameHere")
.petBirthDate(new Date())
.practitionerId("2")
.vetFirstName("VetFirstNameHere")
.vetLastName("VetLastNameHere")
.vetEmail("[email protected]")
.vetPhoneNumber("123-456-7890")
.status(Status.UPCOMING)
.build();
VisitResponseDTO visitResponseDTO2 = VisitResponseDTO.builder()
.visitId("73b5c112-5703-4fb7-b7bc-ac8186811ae1")
.visitDate(LocalDateTime.parse("2024-11-25 13:45", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")))
.description("this is a dummy description")
.petId("2")
.petName("YourPetNameHere")
.petBirthDate(new Date())
.practitionerId("2")
.vetFirstName("VetFirstNameHere")
.vetLastName("VetLastNameHere")
.vetEmail("[email protected]")
.vetPhoneNumber("123-456-7890")
.status(Status.UPCOMING)
.build();
server.enqueue(new MockResponse().setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.setBody(objectMapper.writeValueAsString(Arrays.asList(visitResponseDTO, visitResponseDTO2))).addHeader("Content-Type", "application/json"));

Expand Down Expand Up @@ -93,7 +120,20 @@ void getAllVisits_500Error()throws IllegalArgumentException{

@Test
void getVisitsForStatus() throws JsonProcessingException{
VisitResponseDTO visitResponseDTO = new VisitResponseDTO("773fa7b2-e04e-47b8-98e7-4adf7cfaaeee", LocalDateTime.parse("2024-11-25 13:45", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")), "this is a dummy description", "2", "2", Status.UPCOMING);
VisitResponseDTO visitResponseDTO = VisitResponseDTO.builder()
.visitId("73b5c112-5703-4fb7-b7bc-ac8186811ae1")
.visitDate(LocalDateTime.parse("2024-11-25 13:45", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")))
.description("this is a dummy description")
.petId("2")
.petName("YourPetNameHere")
.petBirthDate(new Date())
.practitionerId("2")
.vetFirstName("VetFirstNameHere")
.vetLastName("VetLastNameHere")
.vetEmail("[email protected]")
.vetPhoneNumber("123-456-7890")
.status(Status.UPCOMING)
.build();
server.enqueue(new MockResponse().setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.setBody(objectMapper.writeValueAsString(visitResponseDTO)).addHeader("Content-Type", "application/json"));

Expand All @@ -114,14 +154,20 @@ void createVisitForPet_Valid() throws JsonProcessingException {
);

// Mock the server response
VisitResponseDTO visitResponseDTO = new VisitResponseDTO(
"73b5c112-5703-4fb7-b7bc-ac8186811ae1",
LocalDateTime.parse("2024-11-25 14:45", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")),
"Test Visit",
"1",
"2",
Status.UPCOMING
);
VisitResponseDTO visitResponseDTO = VisitResponseDTO.builder()
.visitId("73b5c112-5703-4fb7-b7bc-ac8186811ae1")
.visitDate(LocalDateTime.parse("2024-11-25 13:45", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")))
.description("this is a dummy description")
.petId("2")
.petName("YourPetNameHere")
.petBirthDate(new Date())
.practitionerId("2")
.vetFirstName("VetFirstNameHere")
.vetLastName("VetLastNameHere")
.vetEmail("[email protected]")
.vetPhoneNumber("123-456-7890")
.status(Status.UPCOMING)
.build();
server.enqueue(new MockResponse()
.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.setBody(objectMapper.writeValueAsString(visitResponseDTO))
Expand Down Expand Up @@ -248,7 +294,20 @@ void createVisitForPet_InvalidErrorResponse_ThrowsBadRequestException() throws J

@Test
void getVisitsForPet() throws Exception {
VisitResponseDTO visitResponseDTO = new VisitResponseDTO("773fa7b2-e04e-47b8-98e7-4adf7cfaaeee", LocalDateTime.parse("2024-11-25 13:45", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")), "this is a dummy description", "2", "2", Status.UPCOMING);
VisitResponseDTO visitResponseDTO = VisitResponseDTO.builder()
.visitId("73b5c112-5703-4fb7-b7bc-ac8186811ae1")
.visitDate(LocalDateTime.parse("2024-11-25 13:45", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")))
.description("this is a dummy description")
.petId("2")
.petName("YourPetNameHere")
.petBirthDate(new Date())
.practitionerId("2")
.vetFirstName("VetFirstNameHere")
.vetLastName("VetLastNameHere")
.vetEmail("[email protected]")
.vetPhoneNumber("123-456-7890")
.status(Status.UPCOMING)
.build();
server.enqueue(new MockResponse().setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).setBody(objectMapper.writeValueAsString(visitResponseDTO)).addHeader("Content-Type", "application/json"));

Flux<VisitResponseDTO> visits = visitsServiceClient.getVisitsForPet("2");
Expand All @@ -258,7 +317,21 @@ void getVisitsForPet() throws Exception {
}
@Test
void getVisitById() throws Exception {
VisitResponseDTO visitResponseDTO = new VisitResponseDTO("773fa7b2-e04e-47b8-98e7-4adf7cfaaeee", LocalDateTime.parse("2024-11-25 13:45", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")), "this is a dummy description", "2", "2", Status.UPCOMING);
VisitResponseDTO visitResponseDTO = VisitResponseDTO.builder()
.visitId("73b5c112-5703-4fb7-b7bc-ac8186811ae1")
.visitDate(LocalDateTime.parse("2024-11-25 13:45", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")))
.description("this is a dummy description")
.petId("2")
.petName("YourPetNameHere")
.petBirthDate(new Date())
.practitionerId("2")
.vetFirstName("VetFirstNameHere")
.vetLastName("VetLastNameHere")
.vetEmail("[email protected]")
.vetPhoneNumber("123-456-7890")
.status(Status.UPCOMING)
.build();

server.enqueue(new MockResponse().setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).setBody(objectMapper.writeValueAsString(visitResponseDTO)).addHeader("Content-Type", "application/json"));

Mono<VisitResponseDTO> visitResponseDTOMono = visitsServiceClient.getVisitByVisitId("773fa7b2-e04e-47b8-98e7-4adf7cfaaeee");
Expand Down
Loading

0 comments on commit bda738f

Please sign in to comment.