Merge pull request #26 from Safelite/feature/Digital/SSR-93

Feature/digital/ssr 93
This commit is contained in:
Jason Wheeler 2022-11-02 09:04:04 -04:00 committed by GitHub
commit 458c8e2125
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 576 additions and 51 deletions

44
package-lock.json generated
View file

@ -2548,6 +2548,29 @@
"webpack-merge": "^5.7.3", "webpack-merge": "^5.7.3",
"webpack-virtual-modules": "^0.4.2", "webpack-virtual-modules": "^0.4.2",
"whatwg-fetch": "^3.6.2" "whatwg-fetch": "^3.6.2"
},
"dependencies": {
"@vue/vue-loader-v15": {
"version": "npm:vue-loader@15.10.0",
"resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.10.0.tgz",
"integrity": "sha512-VU6tuO8eKajrFeBzMssFUP9SvakEeeSi1BxdTH5o3+1yUyrldp8IERkSdXlMI2t4kxF2sqYUDsQY+WJBxzBmZg==",
"dev": true,
"requires": {
"@vue/component-compiler-utils": "^3.1.0",
"hash-sum": "^1.0.2",
"loader-utils": "^1.1.0",
"vue-hot-reload-api": "^2.3.0",
"vue-style-loader": "^4.1.0"
},
"dependencies": {
"hash-sum": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-1.0.2.tgz",
"integrity": "sha512-fUs4B4L+mlt8/XAtSOGMUO1TXmAelItBPtJG7CyHJfYTdDjwisntGO2JQz7oUsatOY9o68+57eziUVNw/mRHmA==",
"dev": true
}
}
}
} }
}, },
"@vue/cli-shared-utils": { "@vue/cli-shared-utils": {
@ -2797,27 +2820,6 @@
"integrity": "sha512-E2P4oXSaWDqTZNbmKZFVLrNN/siVN78YkEqs7pHryWerrlZR9bBFLWdJwRoguX45Ru6HxIflzKl4vQvwRMwm5g==", "integrity": "sha512-E2P4oXSaWDqTZNbmKZFVLrNN/siVN78YkEqs7pHryWerrlZR9bBFLWdJwRoguX45Ru6HxIflzKl4vQvwRMwm5g==",
"dev": true "dev": true
}, },
"@vue/vue-loader-v15": {
"version": "npm:vue-loader@15.10.0",
"resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.10.0.tgz",
"integrity": "sha512-VU6tuO8eKajrFeBzMssFUP9SvakEeeSi1BxdTH5o3+1yUyrldp8IERkSdXlMI2t4kxF2sqYUDsQY+WJBxzBmZg==",
"dev": true,
"requires": {
"@vue/component-compiler-utils": "^3.1.0",
"hash-sum": "^1.0.2",
"loader-utils": "^1.1.0",
"vue-hot-reload-api": "^2.3.0",
"vue-style-loader": "^4.1.0"
},
"dependencies": {
"hash-sum": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-1.0.2.tgz",
"integrity": "sha512-fUs4B4L+mlt8/XAtSOGMUO1TXmAelItBPtJG7CyHJfYTdDjwisntGO2JQz7oUsatOY9o68+57eziUVNw/mRHmA==",
"dev": true
}
}
},
"@vue/vue3-jest": { "@vue/vue3-jest": {
"version": "27.0.0", "version": "27.0.0",
"resolved": "https://registry.npmjs.org/@vue/vue3-jest/-/vue3-jest-27.0.0.tgz", "resolved": "https://registry.npmjs.org/@vue/vue3-jest/-/vue3-jest-27.0.0.tgz",

View file

@ -3,12 +3,16 @@
<head> <head>
<script> <script>
window.dataLayer = [{}]; window.dataLayer = [{}];
</script> </script>
<script><%= process.env.VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY %></script> <script><%= process.env.VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY %></script>
<meta charset="utf-8"> <meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0"> <meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico"> <link rel="icon" href="<%= BASE_URL %>favicon.ico">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,300;0,400;0,500;0,700;1,300;1,400;1,500;1,700&display=swap" rel="stylesheet">
<title><%= htmlWebpackPlugin.options.title %></title> <title><%= htmlWebpackPlugin.options.title %></title>
</head> </head>
<body> <body>

View file

@ -225,7 +225,7 @@
margin-top: 1.5rem; margin-top: 1.5rem;
margin-bottom: 1rem; margin-bottom: 1rem;
font-size: 1rem; font-size: 1rem;
line-height: 1.625rem; line-height: 1.5rem;
& > span { & > span {
text-align: center; text-align: center;

View file

@ -0,0 +1,21 @@
import { shallowMount } from "@vue/test-utils";
import buttonBack from "./button-back";
describe("back button", () => {
test("renders a button", () => {
// Arrange
const myFunction = () => {};
// Act
const wrapper = shallowMount(buttonBack, {
propsData: {
backButtonAction: myFunction,
backButtonAccessibleText: "something",
},
});
// Assert
expect(wrapper.find("button").exists()).toBe(true);
wrapper.unmount();
});
});

View file

@ -0,0 +1,82 @@
<template>
<button
@click="handleClick"
class="back-button-wrapper"
:aria-label="backButtonAccessibleText"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="34px"
height="30px"
viewBox="-2.2 -6 30 30"
>
<g id="Layer_3">
<path
class="outer"
fill="#FFFFFF"
d="M19.934-1.434h-8.486c-1.683,0-2.999,0.528-4.021,1.614L1.685,6.146C0.78,7.079,0.338,8.027,0.338,9.041
c0,1.028,0.444,1.979,1.359,2.908l5.753,5.938c1.054,1.093,2.403,1.647,4.007,1.647l8.475,0.01c2.861,0,4.568-1.692,4.568-4.528
V3.094C24.5,0.259,22.793-1.434,19.934-1.434L19.934-1.434z"
/>
</g>
<g id="Layer_2">
<path
class="inner"
fill="#727676"
d="M19.934,17.989c2.041,0,3.066-1.006,3.066-3.028V3.039c0-2.022-1.025-3.028-3.066-3.028h-8.486
c-1.143,0-2.129,0.292-2.929,1.143L2.766,7.13C2.131,7.784,1.838,8.37,1.838,8.985c0,0.605,0.283,1.201,0.928,1.855l5.762,5.947
c0.811,0.84,1.787,1.191,2.93,1.191L19.934,17.989z M10.773,13.253c-0.439,0-0.801-0.371-0.801-0.82
c0-0.215,0.078-0.42,0.235-0.566l2.861-2.861l-2.861-2.862c-0.156-0.156-0.234-0.352-0.234-0.566c0-0.458,0.362-0.801,0.801-0.801
c0.224,0,0.41,0.069,0.556,0.225l2.881,2.872l2.891-2.881c0.166-0.166,0.353-0.234,0.566-0.234c0.439,0,0.801,0.352,0.801,0.801
c0,0.225-0.078,0.4-0.234,0.576l-2.871,2.871l2.861,2.852c0.146,0.156,0.234,0.352,0.234,0.576c0,0.449-0.361,0.82-0.811,0.82
c-0.225,0-0.43-0.098-0.586-0.244l-2.852-2.871l-2.852,2.871C11.203,13.165,10.999,13.253,10.773,13.253z"
/>
</g>
</svg>
</button>
</template>
<script>
export default {
name: "buttonBack",
props: {
backButtonAccessibleText: {
type: String,
required: true,
default: "",
},
},
methods: {
handleClick() {
this.$emit("click-event");
},
},
};
</script>
<style lang="scss">
.back-button-wrapper {
padding: 0;
position: relative;
top: -1px;
margin-left: 2px;
border: none;
background: none;
&:focus {
outline: none;
svg .outer {
fill: $white;
stroke-width: 2.5px;
stroke: $blue;
stroke-linecap: round;
stroke-linejoin: round;
transform: translate(-2.7px, -1.8px) scale(1.2);
}
}
&:focus-visible {
outline: none;
}
}
</style>

View file

@ -5,23 +5,39 @@
<span> <span>
{{ content }} {{ content }}
</span> </span>
<buttonBack
v-if="hasBackButton"
:backButtonAccessibleText="backButtonAccessibleText"
@click-event="clickEvent"
/>
</h5> </h5>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import buttonBack from "@/common-components/site-sub-header/button-back/button-back";
export default ({ export default ({
name: "siteSubHeader", name: "siteSubHeader",
props: { props: {
cmsWidgetName: String, cmsWidgetName: String,
hasBackButton: Boolean,
backButtonAccessibleText: String,
}, },
computed: { computed: {
content() content()
{ {
return this.getCmsContent(this.cmsWidgetName, "SubHeaderText") return this.getCmsContent(this.cmsWidgetName, "SubHeaderText")
} }
} },
methods: {
clickEvent() {
this.$emit("click-event");
},
},
components: { buttonBack },
}) })
</script> </script>

View file

@ -9,7 +9,7 @@
</template> </template>
<script> <script>
import { useMainStore } from "@/store";
export default { export default {
name: "vehicle-banner", name: "vehicle-banner",
props: { props: {
@ -25,7 +25,7 @@ export default {
return this.genericVehicleImage; return this.genericVehicleImage;
} }
const imageUrl = this.mainStore.order.vehicle.imageUrl; const imageUrl = useMainStore().order.vehicle.imageUrl;
if (!imageUrl || imageUrl === "NULL"){ if (!imageUrl || imageUrl === "NULL"){
return this.getUnmatchedVehicleIcon(); return this.getUnmatchedVehicleIcon();
} }
@ -53,7 +53,7 @@ export default {
}, },
methods: { methods: {
getUnmatchedVehicleIcon(){ getUnmatchedVehicleIcon(){
switch(this.mainStore.order.vehicle.category){ switch(useMainStore().order.vehicle.category){
case this.vehicleCategories.CAR: case this.vehicleCategories.CAR:
return this.carUnmatchedVehicleIcon; return this.carUnmatchedVehicleIcon;
case this.vehicleCategories.SUV: case this.vehicleCategories.SUV:

View file

@ -15,6 +15,10 @@ const endpoints = {
url: "/vehicle/api/v1/vehicle/years", url: "/vehicle/api/v1/vehicle/years",
method: "GET", method: "GET",
}, },
GetVehicleMakes: {
url: "/vehicle/api/v1/vehicle/makes/",
method: "GET",
},
}; };
export { endpoints }; export { endpoints };

View file

@ -96,7 +96,7 @@ function mapStringToState(str) {
for (const match of globalStateMatches) { for (const match of globalStateMatches) {
// Reset store state for each match. // Reset store state for each match.
let storeState = useMainStore().state; let storeState = useMainStore();
for (const s of match[2].split(".")) { for (const s of match[2].split(".")) {
if (storeState[s] != undefined) { if (storeState[s] != undefined) {

View file

@ -33,7 +33,7 @@ export function getMountOptions(mockData) {
mocks.vehicleCategories = vehicleCategories; mocks.vehicleCategories = vehicleCategories;
mocks.issPageValues = issPageValues; mocks.issPageValues = issPageValues;
mocks.queryStrings = queryStrings; mocks.queryStrings = queryStrings;
mocks.$router = mockData?.router;
const global = { const global = {
mocks: mocks, mocks: mocks,

View file

@ -0,0 +1,70 @@
import makeQuestion from "@/layouts/vehicle-make/make-question/make-question";
import { shallowMount } from "@vue/test-utils";
import { getMountOptions } from "@/helpers/unit-test-helper.js";
import { useMainStore } from "@/store";
describe("make-question.vue", () => {
test("Data from store api are used as radio question answers.", async () => {
//Arrange
const { wrapper, cmsContent } = setupMocks({
dataFromStoreApi: ["honda", "ford", "dodge"],
});
//Act
const initialData = makeQuestion.methods.loadInitialData.call(wrapper.vm);
makeQuestion.methods.initializeComponent.call(
wrapper.vm,
initialData
);
//Assert
const buttonQuestionComponent = await wrapper.findComponent({
name: "buttonQuestion",
});
expect(buttonQuestionComponent.attributes("answers")).toBe(
"honda,ford,dodge"
);
});
test("Selected make is emitted upon selection.", async () => {
//Arrange
const { wrapper } = setupMocks({ modelValueProp: "honda" });
const makeToSelect = "ford";
//Act
wrapper.setValue({ selectedMake: makeToSelect });
await wrapper.vm.$nextTick();
//Assert
expect(wrapper.emitted()["update:modelValue"][0]).toEqual([
{ selectedMake: "ford" },
]);
});
});
function setupMocks({
modelValueProp = "1900",
cmsQuestionText = "CMS text goes here",
dataFromStoreApi = [],
}) {
//Mock store
const mountOptions = getMountOptions();
const store = useMainStore();
store.getVehicleMakes = jest.fn(() => dataFromStoreApi);
mountOptions.propsData = {
modelValue: modelValueProp,
};
const wrapper = shallowMount(makeQuestion, mountOptions);
//Mock CMS content
const cmsContent = {
QuestionText: cmsQuestionText,
};
return { wrapper, cmsContent };
}

View file

@ -0,0 +1,56 @@
<template>
<buttonQuestion
class="radioQuestion"
isOverflowScrollable
selectingInitiatesLoad
:questionText="questionText"
:answers="makes"
groupName="ChooseVehicleMake"
textPosition="text-start"
v-model="selectedValue"
isRequired
/>
</template>
<script>
import buttonQuestion from "@/common-components/button-question/button-question";
import { useMainStore } from '@/store';
export default {
name: "make-question",
data() {
return {
makes: Array,
};
},
props: {
modelValue: String,
cmsWidgetName: String,
},
components: {
buttonQuestion,
},
computed: {
questionText(){
return this.getCmsContent(this.cmsWidgetName, 'QuestionText');
},
selectedValue: {
get: function() {
return this.modelValue
},
set: function(newValue) {
this.$emit("update:modelValue", newValue);
}
}
},
methods: {
loadInitialData() {
return useMainStore().getVehicleMakes();
},
initializeComponent(initialData) {
this.makes = initialData;
},
},
};
</script>

View file

@ -1 +1,140 @@
test.todo("some test to be written in the future"); // Supporting Files
import { shallowMount } from "@vue/test-utils";
import { settleAllPromises } from "@/helpers/layout-helper.js";
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
import baseMixin from "@/mixins/base-mixin.js";
import { getMountOptions } from "@/helpers/unit-test-helper.js";
import { nextTick } from "vue";
import { useMainStore } from "@/store";
// Components
import vehicleMake from "@/layouts/vehicle-make/vehicle-make.vue";
import makeQuestion from "@/layouts/vehicle-make/make-question/make-question";
// Mock fetchCmsContentForPage
jest.mock("@/helpers/cms-content-helper", () => ({
fetchCmsContentForPage: jest.fn(),
}));
// Mock our module for promises.
jest.mock("@/helpers/layout-helper.js", () => ({
settleAllPromises: jest.fn(),
}));
describe("vehicle-make.vue", () => {
test("Make question component is initized with api data", async () => {
//Arrange
const makeQuestionInitialData = ["honda", "ford", "dodge"];
const { wrapper, apiPromise } = setupMocks({
makeQuestionInitialData: makeQuestionInitialData,
});
//Act
vehicleMake.beforeRouteEnter.call(
wrapper.vm,
{ query: { issPage: "vehicle-make" } },
undefined,
(c) => c(wrapper.vm)
);
//Assert
apiPromise.finally(() => {
expect(makeQuestion.methods.initializeComponent).toHaveBeenCalledWith(
makeQuestionInitialData
);
});
});
test("BackButtonAction triggers a router.navigate change", async () => {
//Arrange
const { wrapper, apiPromise } = setupMocks({
pageHeaderWidgetHeaderText: "Select a make to get started",
mountOptionsMockData: {
router: {
navigate: jest.fn(),
},
},
});
//Act
vehicleMake.beforeRouteEnter.call(
wrapper.vm,
{ query: { issPage: "vehicle-make" } },
undefined,
(c) => c(wrapper.vm)
);
wrapper.vm.backButtonAction();
await nextTick();
//Assert
apiPromise.finally(() => {
expect(wrapper.vm.$router.navigate).toHaveBeenCalled();
});
});
test("Year set, arePagePrerequisitesValid should be true ", async () => {
//Arrange
const { wrapper } = setupMocks({});
useMainStore().order.vehicle.year = 2001;
//Act
vehicleMake.beforeRouteEnter.call(
wrapper.vm,
{ query: { issPage: "vehicle-make" } },
undefined,
(c) => c(wrapper.vm)
);
let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid();
//Assert
expect(arePagePrerequisitesValid).toBe(true);
});
});
function setupMocks({
vehicleMakeQuestionCmsContent = {},
makeQuestionInitialData = {},
pageHeaderWidgetHeaderText = {},
mountOptionsMockData = {},
}) {
//Mock api responses
const apiResponses = {
cmsContent: {
SiteSubHeaderWidget: pageHeaderWidgetHeaderText,
VehicleMakeQuestion: vehicleMakeQuestionCmsContent,
VehicleBannerWidget: {
GenericVehicleImage:
"https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/blurred-image.jpg?sfvrsn=a6ce3034_3",
},
SiteHeaderWidget: {
LogoImage:
"https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/safelite-logo.svg?sfvrsn=45e7ed06_3",
},
},
makeQuestionInitialData: makeQuestionInitialData,
};
const apiPromise = Promise.resolve(apiResponses);
settleAllPromises.mockImplementation(() => apiPromise);
fetchCmsContentForPage.mockImplementation(() => Promise.resolve());
//Mock make question methods
makeQuestion.methods = {
loadInitialData: jest.fn(),
initializeComponent: jest.fn(),
};
const mountOptions = getMountOptions(mountOptionsMockData);
const wrapper = shallowMount(vehicleMake, mountOptions);
const makeQuestionWrapper = wrapper.findComponent({ name: "makeQuestion" });
makeQuestionWrapper.vm.initializeComponent =
makeQuestion.methods.initializeComponent;
wrapper.vm.setCmsContent = baseMixin.methods.setCmsContent;
return { wrapper, apiPromise };
}

View file

@ -1,28 +1,102 @@
<template> <template>
<div> <div class="page-container-grouped-styles">
<input type="text" v-model="year"/> <siteHeader cmsWidgetName="SiteHeaderWidget" />
<span> Vehicle Make Placeholder </span> <div class="select-car">
<span>{{returnVehicleYear}}</span> <div class="select-car-form rounded text-center">
<button @click="updateVehicleYear(year)">Add</button> <vehicleBanner cmsWidgetName="VehicleBannerWidget" :displayGenericVehicleImage="true"/>
<siteSubHeader
cmsWidgetName="SiteSubHeaderWidget"
:hasBackButton="true"
@click-event="backButtonAction"
backButtonAccessibleText = "Change vehicle year"
/>
<div class="fade-on-route-transition">
<makeQuestion
class="fade-on-route-transition"
v-model="selectedMake"
ref="makeQuestion"
cmsWidgetName="VehicleMakeQuestion"
/>
</div>
</div>
</div>
</div> </div>
</template> </template>
<script> <script>
// Components
import makeQuestion from "@/layouts/vehicle-make/make-question/make-question";
import siteHeader from "@/common-components/site-header/site-header";
import siteSubHeader from "@/common-components/site-sub-header/site-sub-header";
import vehicleBanner from "@/common-components/vehicle-banner/vehicle-banner";
// Supporting files
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
import { settleAllPromises } from "@/helpers/layout-helper";
export default { export default {
name: 'vehicle-make', name: 'vehicle-make',
methods: data() {
{ return {
updateVehicleYear(item) selectedMake: null,
{ };
this.mainStore.updateVehicleYear(item);
}
}, },
computed:
{ async beforeRouteEnter(to, from, next) {
returnVehicleYear() // Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
const makeQuestionInitialDataPromise = makeQuestion.methods.loadInitialData();
// Settle promises and get results
const promiseResultMap = [
{ {
return this.mainStore.order.vehicle.year; resultKey: "cmsContent",
promise: cmsContentPromise,
},
{
resultKey: "makeQuestionInitialData",
promise: makeQuestionInitialDataPromise,
},
];
let resultMap = await settleAllPromises(promiseResultMap);
// Call the "next" function to complete the transition to this page.
next((vm) => {
vm.setCmsContent(resultMap.cmsContent);
vm.$refs.makeQuestion.initializeComponent(
resultMap.makeQuestionInitialData
);
});
},
methods: {
backButtonAction() {
this.$router.navigate(
this.navigationScenarios.CLICKED_BACK,
this.$route
);
},
arePagePrerequisitesValid() {
if (this.mainStore.order.vehicle.year){
return true;
} }
} return false;
} },
},
components: {
makeQuestion,
siteHeader,
siteSubHeader,
vehicleBanner,
},
watch: {
selectedMake(make) {
this.mainStore.updateVehicleMake(make);
this.$router.navigate(
this.navigationScenarios.SELECTED_MAKE,
this.$route
);
},
},
};
</script> </script>

View file

@ -3,7 +3,7 @@
<siteHeader cmsWidgetName="SiteHeaderWidget" /> <siteHeader cmsWidgetName="SiteHeaderWidget" />
<div class="select-car"> <div class="select-car">
<div class="select-car-form rounded text-center"> <div class="select-car-form rounded text-center">
<vehicleBanner cmsWidgetName="VehicleBannerWidget" displayGenericVehicleImage="true"/> <vehicleBanner cmsWidgetName="VehicleBannerWidget" :displayGenericVehicleImage="true"/>
<siteSubHeader cmsWidgetName="SiteSubHeaderWidget" /> <siteSubHeader cmsWidgetName="SiteSubHeaderWidget" />
<div class="fade-on-route-transition"> <div class="fade-on-route-transition">
<yearQuestion <yearQuestion
@ -65,6 +65,22 @@
); );
}); });
}, },
watch: {
selectedYear(year) {
const parsedYear = parseInt(year);
this.mainStore.updateVehicleYear(parsedYear);
this.$router.navigate(
this.navigationScenarios.SELECTED_YEAR,
this.$route
);
},
},
methods: {
arePagePrerequisitesValid() {
return true;
},
},
components: { components: {
yearQuestion, yearQuestion,

View file

@ -5,7 +5,7 @@ const navigationScenarios = {
// YMMS // YMMS
SELECTED_YEAR: "SELECTED_YEAR", SELECTED_YEAR: "SELECTED_YEAR",
SELECTED_MAKE: "SELECTED_MAKE",
// TESTING // TESTING
CLICKED_TEST: "CLICKED_TEST" CLICKED_TEST: "CLICKED_TEST"
}; };

View file

@ -11,6 +11,23 @@ const routingTable = function(store) {
scenario: navigationScenarios.CLICKED_BACK, scenario: navigationScenarios.CLICKED_BACK,
destinationIssPageValue: issPageValues.WELCOME_PAGE destinationIssPageValue: issPageValues.WELCOME_PAGE
}, },
{
scenario: navigationScenarios.SELECTED_YEAR,
destinationIssPageValue: issPageValues.VEHICLE_MAKE
},
],
},
{
issPageValue: issPageValues.VEHICLE_MAKE,
maps: [
{
scenario: navigationScenarios.CLICKED_BACK,
destinationIssPageValue: issPageValues.VEHICLE_YEAR
},
{
scenario: navigationScenarios.SELECTED_MAKE,
destinationIssPageValue: issPageValues.WELCOME_PAGE
},
], ],
}, },
{ {
@ -26,6 +43,7 @@ const routingTable = function(store) {
} }
] ]
}, },
]; ];
}; };

View file

@ -83,6 +83,14 @@ export const useMainStore = defineStore({
}); });
}, },
getVehicleMakes() {
return globalMethods.callHttpClient({
method: endpoints.GetVehicleMakes.method,
endpoint: endpoints.GetVehicleMakes.url + this.order.vehicle.year,
payload: {},
});
},
// Vehicle API Actions // Vehicle API Actions
updateVehicleYear(year) updateVehicleYear(year)
{ {
@ -91,6 +99,13 @@ export const useMainStore = defineStore({
} }
}, },
updateVehicleMake(make)
{
if (this.order.vehicle.make !== make) {
this.order.vehicle.make = make;
}
},
// populate initial state // populate initial state
populateInitialState() populateInitialState()
{ {

View file

@ -0,0 +1,6 @@
//Custom Mixins
//Blue gradient background mixin
@mixin blue-gradient {
background: linear-gradient(270deg, $blue 0%, $blue-800 100%);
}

View file

@ -19,6 +19,7 @@ module.exports = {
@import "@/styles/ux-variables.scss"; @import "@/styles/ux-variables.scss";
@import "./node_modules/bootstrap/scss/variables"; @import "./node_modules/bootstrap/scss/variables";
@import "./node_modules/bootstrap/scss/mixins"; @import "./node_modules/bootstrap/scss/mixins";
@import "@/styles/mixins/customMixins";
`, `,
}, },
}, },

View file

@ -17,10 +17,11 @@ module.exports = {
@import "@/styles/ux-variables.scss"; @import "@/styles/ux-variables.scss";
@import "./node_modules/bootstrap/scss/variables"; @import "./node_modules/bootstrap/scss/variables";
@import "./node_modules/bootstrap/scss/mixins"; @import "./node_modules/bootstrap/scss/mixins";
@import "@/styles/mixins/customMixins";
`, `,
}, },
}, },
}, },
configureWebpack: { configureWebpack: {
devtool: 'source-map' devtool: 'source-map'
}, },