Owner Management Portal
- Angular
- SCSS
- JSP
- Java
An Angular 11 application living inside a legacy Java application to guide users through common functions of the Owner Account Management portal.
- Designer Angela Shockey
- Lead Angular Developer Josh Delgado
-
Angular Developers
Rebecca Terry,
Shianne Dyges -
Java Developers
Khondaker Sadman,
Francisco Felix - Client Westgate Resorts
The Problem(s)
This was one of the older projects in the company's codebase which means there was A LOT of undocumneted and spaghetti code. Few developers wanted to work on the project since it was difficult to find the code you needed to address and when you did, it would often change something else in addition.
The demographic for this application skews older and less tech-savvy so support calls and messages were aggressively high.
This is a the first part of a multi-phase transition to an entirely angular application. The phase one purpose was to create a guided flow that would direct the user to the existing page to complete their goal. Since this was an addition to the site instead of a conversion, it allowed our team to discover pitfalls in our design through live user testing.
The Project
The Process
The Angular application lives within the existing Java/JSP website. Angular preloads the base module and remains hidden until the user clicks the "Show Guided Flow" bar that exists throughout the website.
<app-guided-flow-heading [heading]="'guidedFlow.step.init.title' | messageBundle"
[welcome]="'guidedFlow.header.welcome' | messageBundle: userName"></app-guided-flow-heading>
<div class="init-step">
<app-guided-flow-card class="init-step__card-socket"
[card]="card"
[highlightCard]="first"
*ngFor="let card of response.cards; let first=first;"></app-guided-flow-card>
</div>
<app-guided-flow-footer [additionalOptions]="response.additionalOptions"></app-guided-flow-footer>
<app-flow-actions [isFirstStep]="true"></app-flow-actions>
import {Component, OnInit} from '@angular/core';
import {ActivatedRoute} from "@angular/router";
import {BaseStep} from '../../../../common/components/steps/base-step/base-step';
import {GuidedFlowStoreService} from "../../../../common/services/guided-flow-store.service";
@Component({
selector: 'app-init-step',
templateUrl: './init-step.component.html',
styleUrls: ['./init-step.component.scss'],
})
export class InitStepComponent extends BaseStep implements OnInit {
userName: string;
constructor(protected activatedRoute: ActivatedRoute,
protected guidedFlowStoreService: GuidedFlowStoreService) {
super(activatedRoute, guidedFlowStoreService);
}
ngOnInit(): void {
super.initStep();
this.activatedRoute.data.subscribe((data) => {
this.userName = data.greeting;
});
}
}
import {ActivatedRoute} from "@angular/router";
import {GuidedFlowStep} from "../../../domain/guided-flow-step";
import {Directive} from '@angular/core';
import {GuidedFlowStoreService} from "../../../services/guided-flow-store.service";
@Directive()
export class BaseStep {
response: GuidedFlowStep;
loading: boolean = false;
constructor(protected activatedRoute: ActivatedRoute,
protected guidedFlowStoreService: GuidedFlowStoreService) {
}
initStep(): void {
this.activatedRoute.data.subscribe((data) => {
this.response = data.response;
});
this.guidedFlowStoreService.setPageTitle(undefined);
}
}
It has a data-driven, card-based design reduces the number of front-end components that need to be written.
The project is split into multiple modules to reduce bandwidth and speed up page load times.
The user base is 90% desktop users (the demographic skews older) but the development is still mobile focused.
We utilize Angular Material Forms and Icons to do some of the heavy lifting and reduce our development time. Who wants to reinvent the wheel?
@Injectable({
providedIn: 'root'
})
export class GuidedFlowHttpService {
readonly baseUrl: string = 'service/guided-flow/';
readonly profileUrl: string = 'service/profile/';
constructor(private httpService: HttpService) {
}
getGreeting(): Promise<any> {
return this.httpService.get<any>(this.baseUrl + 'greeting/', {responseType: 'text'});
}
getInitialGuidedFlow(cardLimit: number): Promise<GuidedFlowStep> {
return this.httpService.get<GuidedFlowStep>(this.baseUrl + 'initial/', {params: {cardLimit: cardLimit}}, GuidedFlowStep);
}
}
@RestController
@RequestMapping("/service/guided-flow")
public class GuidedFlowServiceController {
@Autowired
@Qualifier("westgateGuidedFlowService")
private WestgateGuidedFlowService westgateGuidedFlowService;
@Autowired
@Qualifier("reservationsWestgateGuidedFlowService")
private ReservationsWestgateGuidedFlowService reservationsWestgateGuidedFlowService;
@Autowired
private CompanySettings companySettings;
@GetMapping("/initial")
public WGRGuidedFlowStep getInitialGuidedFlow(@RequestParam("cardLimit") int cardLimit) {
if (UserUtil.isVacpacUser()) {
return reservationsWestgateGuidedFlowService.getInitialGuidedFlowStep(UserUtil.getVacpacUserDetails());
} else {
return westgateGuidedFlowService.getInitialGuidedFlowStep(UserUtil.getWestgateUserDetails(), cardLimit);
}
}
}
We create Angular analogs for services, objects, etc that exist on the Java side. This helps our front-end and back-end devs communicate and eliminates many common misunderstandings.
Conclusion
This project pushed us to bring our common angular library to the next level with further abstractions and increased organization. It was a pain at first to stop development to work on the library but the time has already been made up for.
Early user testing has been received well. The common use-cases are much easier for our applications demographic to navigate through.
Going forward, more documentation for the project is needed. As it's an in-progress application, certain patterns are still up for debate so we haven't written extensive documentation for it. If you'd like to see examples of my documentation style you can do so here.
And lastly, If you happen to have a Westgate account, check it out!
Get In Touch
I'm not actively looking for new oppourtunities but I'm not a hermit. Reach out with questions, comments, or even just to say hey.
Say What's Up