Merge pull request #977 from Safelite/feature/richardson/INSR-7779

remove loader in continue button
This commit is contained in:
brich1212safe 2025-12-10 15:40:13 -05:00 committed by GitHub
commit e42cb26706
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
28 changed files with 83 additions and 545 deletions

View file

@ -2,8 +2,12 @@
<div
class="date-picker text-center"
:class="[calendarViewDirection, { 'has-error': errors.length > 0 }]">
<fieldset id="date-picker-fieldset" ref="datePickerFieldset">
<legend class="sr-only">Select a day and time</legend>
<fieldset
id="date-picker-fieldset"
ref="datePickerFieldset">
<legend class="sr-only">
Select a day and time
</legend>
<div
v-for="month in months"
:id="`${month.monthLabel}-${month.yearNum?.toString()}`"
@ -80,12 +84,12 @@
</label>
</div>
</div>
<loader
:class="[!isLoading ? 'date-picker-hidden' : '']"
loaderColor="blue"
loaderPosition="center" />
<div id="date-of-month-error" class="row form-test-error">
<ErrorMessage :name="customComponentId" class="small mt-1">
<div
id="date-of-month-error"
class="row form-test-error">
<ErrorMessage
:name="customComponentId"
class="small mt-1">
</ErrorMessage>
</div>
<button
@ -106,7 +110,6 @@
<script>
// Supporting files
import loader from '@/ux-components/loader/loader.vue';
import { useMainStore } from '@/store';
import { useField, ErrorMessage } from 'vee-validate';
import { deepClone } from '@/helpers/object-helper';
@ -124,7 +127,6 @@ import { selectableDaysOptions, requiredParameter } from './mixins/helpers';
export default {
name: 'date-picker',
components: {
loader,
ErrorMessage
},
props: {
@ -206,8 +208,8 @@ export default {
computed: {
todayString() {
return (
this.todayOverrideDateString ||
convertDateToDateString(new Date())
this.todayOverrideDateString
|| convertDateToDateString(new Date())
);
},
todayDayIndex() {
@ -307,9 +309,7 @@ export default {
let weekEndDate = this.getWeekEndDate(todayString);
if (preSelectedDateString) {
const preSelectedDateMonthEnd = this.getMonthEnd(
preSelectedDateString
);
const preSelectedDateMonthEnd = this.getMonthEnd(preSelectedDateString);
let weekIncludesPreSelectedMonthEnd = false;
let i = 0;
while (!weekIncludesPreSelectedMonthEnd) {
@ -318,10 +318,10 @@ export default {
weekEndDate = this.getWeekEndDate(weekStartDate);
if (
(preSelectedDateMonthEnd > weekStartDate &&
preSelectedDateMonthEnd < weekEndDate) ||
preSelectedDateMonthEnd === weekStartDate ||
preSelectedDateMonthEnd === weekEndDate
(preSelectedDateMonthEnd > weekStartDate
&& preSelectedDateMonthEnd < weekEndDate)
|| preSelectedDateMonthEnd === weekStartDate
|| preSelectedDateMonthEnd === weekEndDate
) {
weekEndDate = preSelectedDateMonthEnd;
weekIncludesPreSelectedMonthEnd = true;
@ -349,8 +349,8 @@ export default {
// If any of these weeks is split between two months, then make them 2 separate "weeks"
// (a week split between two months is considered 2 weeks per business requirements)
const hasSplitWeek = (week) =>
week.weekStartDate.split('-')[1] !==
week.weekEndDate.split('-')[1];
week.weekStartDate.split('-')[1]
!== week.weekEndDate.split('-')[1];
const splitWeekIndex = weeks.findIndex(hasSplitWeek);
if (splitWeekIndex > -1) {
@ -359,9 +359,7 @@ export default {
let switchToWeek2 = false;
for (let j = 0; j < 7; j++) {
const newDate = convertDateStringToDate(
weeks[splitWeekIndex].weekStartDate
);
const newDate = convertDateStringToDate(weeks[splitWeekIndex].weekStartDate);
newDate.setDate(newDate.getDate() + j);
if (newDate.getDate() === 1) switchToWeek2 = true;
if (switchToWeek2) {
@ -412,10 +410,8 @@ export default {
} else {
todayDateString = convertDateToDateString(new Date());
}
if (config.selectableDatesSetting === 'past')
calendarViewDirection = 'past';
if (config.selectableDatesSetting === 'custom')
calendarViewDirection = 'future';
if (config.selectableDatesSetting === 'past') calendarViewDirection = 'past';
if (config.selectableDatesSetting === 'custom') calendarViewDirection = 'future';
const currentMonthEnd = this.getMonthEnd(todayDateString);
// TODO - set up currentMonthStart if direction is PAST:
@ -484,11 +480,9 @@ export default {
const direction = config.calendarViewDirection;
const monthsAfterToLoadOffset = 6;
const monthsBeforeToLoadOffset = 36;
config.initialShopTimeSlotsResponse.days.forEach(
(selectableDate) => {
this.selectableDatesData.push(selectableDate);
}
);
config.initialShopTimeSlotsResponse.days.forEach((selectableDate) => {
this.selectableDatesData.push(selectableDate);
});
// GENERATE MONTHS AND PUSH THEM INTO ARRAY
const months = [];
@ -524,11 +518,10 @@ export default {
this.$nextTick(() => {
// Advance to month
const monthToShow = this.months.find((month) =>
month.monthClass.includes('month-preselected')
);
month.monthClass.includes('month-preselected'));
if (
monthToShow.monthClass.includes('month-preselected') &&
monthToShow.monthClass.includes('last-available-month')
monthToShow.monthClass.includes('month-preselected')
&& monthToShow.monthClass.includes('last-available-month')
) {
// disable View More dates button if the preSelectedDate in the last available month
this.disableViewMoreDatesButton = true;
@ -553,12 +546,10 @@ export default {
*/
let monthNum =
convertDateStringToDate(this.todayString).getMonth() +
offset +
1;
let yearNum = convertDateStringToDate(
this.todayString
).getFullYear();
convertDateStringToDate(this.todayString).getMonth()
+ offset
+ 1;
let yearNum = convertDateStringToDate(this.todayString).getFullYear();
const { calendarViewDirection } = options;
if (calendarViewDirection === 'future' && offset > 0) {
while (monthNum > 12) {
@ -595,18 +586,18 @@ export default {
let monthEndDateNum = monthEndDate.getDate();
if (
offset === 0 &&
calendarViewDirection === 'past' &&
monthEndDateNum > this.currentWeekEndDateNum
offset === 0
&& calendarViewDirection === 'past'
&& monthEndDateNum > this.currentWeekEndDateNum
) {
monthEndDateNum = this.currentWeekEndDateNum;
}
if (options.preSelectedDate) {
if (
monthStartDate.getFullYear() ===
preSelectedDateObj.getFullYear() &&
monthStartDate.getMonth() === preSelectedDateObj.getMonth()
monthStartDate.getFullYear()
=== preSelectedDateObj.getFullYear()
&& monthStartDate.getMonth() === preSelectedDateObj.getMonth()
) {
monthClass += ' month-preselected';
} else if (monthStartDate > preSelectedDateObj) {
@ -619,14 +610,14 @@ export default {
}
if (
Math.abs(offset) === options.monthsAfterToLoadOffset &&
calendarViewDirection === 'future'
Math.abs(offset) === options.monthsAfterToLoadOffset
&& calendarViewDirection === 'future'
) {
monthClass += ' last-available-month';
}
if (
Math.abs(offset) === options.monthsBeforeToLoadOffset &&
calendarViewDirection === 'past'
Math.abs(offset) === options.monthsBeforeToLoadOffset
&& calendarViewDirection === 'past'
) {
// TODO - re-check this logic if past direction
monthClass += ' last-available-month';
@ -635,24 +626,22 @@ export default {
// populate dates array
for (let i = monthStartDateNum; i <= monthEndDateNum; i++) {
let dayClasses = '';
const dateString = `${yearNum.toString()}-${`0${monthNum}`.slice(
-2
)}-${`0${i}`.slice(-2)}`;
const dateString = `${yearNum.toString()}-${`0${monthNum}`.slice(-2)}-${`0${i}`.slice(-2)}`;
if (offset === 0 && i === this.todayDateNum) {
dayClasses += ' current-day';
}
if (
offset === 0 &&
i < this.todayDateNum &&
calendarViewDirection === 'future'
offset === 0
&& i < this.todayDateNum
&& calendarViewDirection === 'future'
) {
dayClasses += ' unavailable-day';
}
if (
offset === 0 &&
i > this.todayDateNum &&
calendarViewDirection === 'past'
offset === 0
&& i > this.todayDateNum
&& calendarViewDirection === 'past'
) {
dayClasses += ' unavailable-day';
}
@ -660,11 +649,11 @@ export default {
dayClasses += ' sunday';
}
if (
this.hideSomeDaysForInitialView &&
convertDateStringToDate(initialViewEndDate).getMonth() +
1 ===
monthNum &&
convertDateStringToDate(initialViewEndDate).getDate() < i
this.hideSomeDaysForInitialView
&& convertDateStringToDate(initialViewEndDate).getMonth()
+ 1
=== monthNum
&& convertDateStringToDate(initialViewEndDate).getDate() < i
) {
dayClasses += ' day-hidden';
isMonthThatHidesSomeDaysForInitialView = true;
@ -674,9 +663,7 @@ export default {
dayClasses,
inputValue: dateString,
isSelectable:
this.selectableDatesData.findIndex(
(date) => date.date === dateString
) > -1
this.selectableDatesData.findIndex((date) => date.date === dateString) > -1
};
dates.push(dateObject);
}
@ -701,26 +688,21 @@ export default {
let monthStartDateNum = 0;
if (this.hideSomeDaysForInitialView) {
monthToShow = this.months.find(
({ isMonthThatHidesSomeDaysForInitialView }) =>
isMonthThatHidesSomeDaysForInitialView
);
monthToShow = this.months.find(({ isMonthThatHidesSomeDaysForInitialView }) =>
isMonthThatHidesSomeDaysForInitialView);
// find the first day-hidden to become the next api call start date
monthStartDateNum =
monthToShow.dates.find(({ dayClasses }) =>
dayClasses.includes('day-hidden')
).dateNum - 1;
dayClasses.includes('day-hidden')).dateNum - 1;
} else {
if (this.calendarViewDirection === 'future') {
monthToShow = this.months.find((month) =>
month.monthClass.includes('month-hidden')
);
month.monthClass.includes('month-hidden'));
}
if (this.calendarViewDirection === 'past') {
// TODO: UPDATE THIS WITH CORRECT PAST LOOKING LOGIC
monthToShow = this.months.find((month) =>
month.monthClass.includes('month-hidden')
);
month.monthClass.includes('month-hidden'));
}
}
if (monthToShow) {
@ -737,8 +719,7 @@ export default {
);
this.scrollToElement(monthToShow.monthString);
if (monthToShow.monthClass.includes('last-available-month'))
this.disableViewMoreDatesButton = true;
if (monthToShow.monthClass.includes('last-available-month')) this.disableViewMoreDatesButton = true;
}
},
async updateSelectableDates(monthStart, monthEnd) {
@ -751,9 +732,7 @@ export default {
);
moreSelectableDates.days.forEach((selectableDate) => {
const index = this.selectableDatesData.findIndex(
(dateObj) => dateObj.date === selectableDate.date
);
const index = this.selectableDatesData.findIndex((dateObj) => dateObj.date === selectableDate.date);
if (index === -1) this.selectableDatesData.push(selectableDate);
this.months.forEach((month) => {
// TODO: avoid checking all calendar dates; maybe only ones between monthStart and monthEnd as defined above?
@ -821,19 +800,6 @@ export default {
flex-grow: 1;
position: relative;
}
.loader {
height: 2rem;
width: 100%;
display: flex;
justify-content: center;
transform: unset;
right: unset;
&::after {
width: 1.5rem;
height: 1.5rem;
}
}
.calendar-grid-container {
margin: 0 auto 2rem auto;
max-width: 414px;

View file

@ -19,9 +19,6 @@
align-items-center justify-content-center d-inline-flex mt-2 py-3 px-4 delay w-100"
@click="continueReferral">
{{ modalBodyText }}
<loader
v-if="isLoaderDisplayed"
class="ms-2 button-loader" />
</button>
</modal>
</div>
@ -29,20 +26,17 @@
</template>
<script>
import loader from '@/ux-components/loader/loader.vue';
import modal from '@/digital-components/modal/modal.vue';
import { getISSCookie } from '@/helpers/cookie-helper.js';
export default {
name: 'continue-modal',
components: {
loader,
modal
},
emits: ['continue-previous-referral', 'start-new-referral'],
data() {
return {
isLoaderDisplayed: false,
isModalOpened: false
};
},
@ -69,9 +63,6 @@ export default {
openModal() {
this.$refs.continueModal.openModal();
},
removeLoader() {
this.isLoaderDisplayed = false;
},
setModalStatus(isOpened) {
this.isModalOpened = isOpened;
},
@ -79,7 +70,6 @@ export default {
this.$refs.continueModal.closeModal();
},
continueReferral() {
this.isLoaderDisplayed = true;
this.$emit('continue-previous-referral');
},
startNewReferral() {

View file

@ -294,32 +294,6 @@ describe('Shop list button', () => {
expect(availabilityIndicatorBlock.classes()).toContain('availability-indicator');
expect(availabilityIndicatorBlock.classes()).toContain('rounded-pill');
});
test('availability indicator loader when displayAvailabilityIndicators', async () => {
// Arrange
const additionalButtonData = {
displayAvailabilityIndicators: true,
availabilityRatingCallback: () => Promise.resolve(null)
};
const wrapper = mount(shopListButton, {
propsData: {
value: 1234,
modelValue: 'value of modal',
groupName: 'name of group',
buttonLabel: 'label of button',
additionalButtonData
},
mixins: [inputButtonWrapperMixin]
});
await wrapper.vm.$nextTick();
// Act
const availabilityIndicatorLoader = wrapper.findComponent(loaderReference);
// Assert
expect(availabilityIndicatorLoader.exists()).toBeTruthy();
expect(availabilityIndicatorLoader.props().loaderPosition).toBe('left');
expect(availabilityIndicatorLoader.props().allowPageInteraction).toBe(true);
});
describe('availability badge when displayAvailabilityIndicators true', () => {
test('and "availabilityRating" is "high"', async () => {
// Arrange
@ -437,60 +411,6 @@ describe('Shop list button', () => {
});
});
describe('should not render', () => {
test.each([false, null, undefined])(
'availability indicator block when displayAvailabilityIndicators falsy',
async (displayAvailabilityIndicators) => {
// Arrange
const additionalButtonData = {
displayAvailabilityIndicators,
availabilityRatingCallback: () => Promise.resolve({})
};
const wrapper = mount(shopListButton, {
propsData: {
value: 1234,
modelValue: 'value of modal',
groupName: 'name of group',
buttonLabel: 'label of button',
additionalButtonData
},
mixins: [inputButtonWrapperMixin]
});
await wrapper.vm.$nextTick();
// Act
const availabilityIndicatorBlock = wrapper.find(availabilityIndicatorBlockReference);
// Assert
expect(availabilityIndicatorBlock.exists()).toBeFalsy();
}
);
test.each([null, undefined])(
'availability badge when displayAvailabilityIndicators true and "availabilityRating" is null',
async (availabilityRating) => {
// Arrange
const additionalButtonData = {
displayAvailabilityIndicators: true,
availabilityRatingCallback: () => Promise.resolve(availabilityRating)
};
const wrapper = mount(shopListButton, {
propsData: {
value: 1234,
modelValue: 'value of modal',
groupName: 'name of group',
buttonLabel: 'label of button',
additionalButtonData
},
mixins: [inputButtonWrapperMixin]
});
await wrapper.vm.$nextTick();
// Act
const availabilityBadge = wrapper.find(availabilityBadgeReference);
// Assert
expect(availabilityBadge.exists()).toBeFalsy();
}
);
test('button body copy when buttonBodyCopy not provided', async () => {
// Arrange
const additionalButtonData = {
@ -542,33 +462,6 @@ describe('Shop list button', () => {
});
describe('computed', () => {
describe('isLoaderDisplayed', () => {
test.each([null, undefined])(
'should return true when availabilityRating is null or undefined',
async (availabilityRating) => {
// Arrange
const additionalButtonData = {
displayAvailabilityIndicators: true,
availabilityRatingCallback: () => Promise.resolve(availabilityRating)
};
const wrapper = mount(shopListButton, {
propsData: {
value: 1234,
modelValue: 'value of modal',
groupName: 'name of group',
buttonLabel: 'label of button',
additionalButtonData
},
mixins: [inputButtonWrapperMixin]
});
await wrapper.vm.$nextTick();
// Act
const result = wrapper.vm.isLoaderDisplayed;
// Assert
expect(result).toBeTruthy();
}
);
test('should return false when availabilityRating is empty string', async () => {
// Arrange
const availabilityRating = '';

View file

@ -25,13 +25,7 @@
id="availabilityIndicatorBlock"
class="availability-indicator rounded-pill"
:class="availabilityRatingClass">
<loader
v-if="isLoaderDisplayed"
ref="availabilityIndicatorLoader"
loaderPosition="left"
:allowPageInteraction="true" />
<div
v-else
id="availabilityIndicator"
class="d-flex align-items-center">
<div
@ -64,13 +58,11 @@
<script>
import baseInputButton from '@/digital-components/base-input-button/base-input-button.vue';
import inputButtonWrapperMixin from '@/mixins/input-button-wrapper-mixin';
import loader from '@/ux-components/loader/loader.vue';
export default {
name: 'shop-list-button',
components: {
baseInputButton,
loader
baseInputButton
},
mixins: [inputButtonWrapperMixin],
data() {
@ -80,9 +72,6 @@ export default {
};
},
computed: {
isLoaderDisplayed() {
return this.availabilityRating == null;
},
availabilityRatingClass() {
if (this.availabilityRating != null) {
return this.availabilityRating === 'high' ? 'green' : 'orange';
@ -203,18 +192,6 @@ export default {
align-items: center;
}
.loader {
padding: 0 0.25rem 0 0.25rem;
padding-top: 0.125rem;
padding-bottom: 0.125rem;
}
.loader:after {
background-color: $gray-550;
height: 1rem;
width: 1rem;
}
&.green {
color: $green-700;
background-color: $green-100;

View file

@ -94,10 +94,6 @@ export default {
updateButtonText(newText) {
this.customButtontext = newText;
},
removeLoader() {
this.$refs.buttonMain.removeLoader();
document.onkeydown = () => true;
},
buttonClick() {
// prevent keyboard input after button click
document.onkeydown = () => false;

View file

@ -88,7 +88,6 @@ function setupMocks({
wrapper.vm.$router.navigateWithSpinner = jest.fn();
wrapper.vm.navigateBack = baseMixin.methods.navigateBack;
wrapper.vm.$refs.siteFooter.updateButtonText = jest.fn();
wrapper.vm.$refs.siteFooter.removeLoader = jest.fn();
wrapper.vm.$refs.siteFooter.disableForwardButton = jest.fn();
wrapper.vm.$refs.siteFooter.enableForwardAction = jest.fn();
@ -483,7 +482,7 @@ describe('address-lookup.vue', () => {
const { wrapper } = setupMocks({
vinVehicles: [
{
{
vehicle: {
carId: 'BIGTRUCKCARID',
isBigTruck: true,
@ -498,7 +497,7 @@ describe('address-lookup.vue', () => {
await wrapper.setData({
customerQuestions: {
addressQuestions: mockRegistrationAddress
},
}
});
// Act
@ -518,7 +517,7 @@ describe('address-lookup.vue', () => {
const { wrapper } = setupMocks({
vinVehicles: [
{
{
vehicle: {
carId: 'BIGTRUCKCARID2',
isBigTruck: true,
@ -533,7 +532,7 @@ describe('address-lookup.vue', () => {
await wrapper.setData({
customerQuestions: {
addressQuestions: mockRegistrationAddress
},
}
});
// Act

View file

@ -250,8 +250,7 @@ export default {
if (!resultMap.vinLookupResponse.isStatePermissible) {
// State Restrictions forbid lookup by address
this.displayVinLookupByHomeAddressNotAllowedAlert = true;
this.$refs.siteFooter.disableForwardButton();
return this.$refs.siteFooter.removeLoader();
return this.$refs.siteFooter.disableForwardButton();
}
const carsFound = resultMap.vinLookupResponse.vinVehicles;
@ -263,12 +262,10 @@ export default {
if (!carFound.canSafeliteService) {
this.displayNoServiceAlert = true;
this.$refs.siteFooter.disableForwardButton();
return this.$refs.siteFooter.removeLoader();
return this.$refs.siteFooter.disableForwardButton();
}
this.isCarIdDifferent =
carFound.carId !== useMainStore().order.vehicle.carId;
this.isCarIdDifferent = carFound.carId !== useMainStore().order.vehicle.carId;
if (this.isCarIdDifferent && carFound.carId !== this.previouslyEnteredCarId) {
// Display Alert
this.previouslyEnteredCarId = carFound.carId;
@ -284,10 +281,9 @@ export default {
await isGlassAvailableForCarId(carFound.carId);
// Update button "Continue with..."
this.$refs.siteFooter
return this.$refs.siteFooter
// eslint-disable-next-line max-len
.updateButtonText(`Continue with ${carFound.year} ${carFound.make} ${carFound.model} ${this.forwardButtonCarStyle}`);
return this.$refs.siteFooter.removeLoader();
}
// update data
@ -310,8 +306,7 @@ export default {
} else {
// No VINS found.
this.displayVinNotFoundAlert = true;
this.$refs.siteFooter.disableForwardButton();
return this.$refs.siteFooter.removeLoader();
return this.$refs.siteFooter.disableForwardButton();
}
// Save vehicle, customer, service and registration information

View file

@ -119,7 +119,6 @@ function setupMocks({
wrapper.vm.$router.navigateWithSpinner = jest.fn();
wrapper.vm.navigateBack = baseMixin.methods.navigateBack;
wrapper.vm.$refs.siteFooter.updateButtonText = jest.fn();
wrapper.vm.$refs.siteFooter.removeLoader = jest.fn();
wrapper.vm.$refs.siteFooter.disableForwardButton = jest.fn();
return { wrapper };
@ -147,7 +146,6 @@ describe('address-vehicles.vue', () => {
};
wrapper.vm.$refs.siteFooter.updateButtonText = jest.fn();
wrapper.vm.$refs.siteFooter.removeLoader = jest.fn();
wrapper.vm.lookupVin = jest.fn(() => Promise.resolve(lookupVinResponse));
wrapper.vm.$router.navigate = jest.fn();
wrapper.vm.saveVin = jest.fn().mockImplementation(() => {});
@ -176,7 +174,6 @@ describe('address-vehicles.vue', () => {
};
wrapper.vm.$refs.siteFooter.updateButtonText = jest.fn();
wrapper.vm.$refs.siteFooter.removeLoader = jest.fn();
wrapper.vm.lookupVin = jest.fn(() => Promise.reject(lookupVinResponse));
wrapper.vm.$router.navigate = jest.fn();
wrapper.vm.saveVin = jest.fn().mockImplementation(() => {});
@ -323,7 +320,7 @@ describe('address-vehicles.vue', () => {
selectedVehicleVin: 'BIGTRUCKVIN2',
previouslyEnteredCarId: 'BIGTRUCKCARID2'
});
2
wrapper.vm.selectedVehicle = {
vin: 'BIGTRUCKVIN2',
vehicle: {

View file

@ -259,16 +259,11 @@ export default {
return false;
},
async forwardButtonAction() {
const vinLookup = await useMainStore()
.lookupVehicleByVin(this.selectedVehicle.vin)
.catch(() => {
this.$refs.siteFooter.removeLoader();
});
const vinLookup = await useMainStore().lookupVehicleByVin(this.selectedVehicle.vin);
if (!vinLookup) {
return;
}
this.isSelectedGlassAvailableForVehicle =
await isGlassAvailableForCarId(vinLookup.data.carId);
this.isSelectedGlassAvailableForVehicle = await isGlassAvailableForCarId(vinLookup.data.carId);
await useMainStore().saveVin(
{
vehicleInfo: Object.assign(this.selectedVehicle.vehicle, {

View file

@ -2,7 +2,6 @@
exports[`returns the initial data 1`] = `
Object {
"isLoaderDisplayed": false,
"isModalOpened": false,
}
`;

View file

@ -21,9 +21,6 @@
align-items-center justify-content-center d-inline-flex mt-4 py-3 px-4 delay w-100"
@click="returnToClaim">
{{ modalBodyText2 }}
<loader
v-if="isLoaderDisplayed"
class="ms-2 button-loader" />
</button>
</modal>
</div>
@ -31,19 +28,16 @@
</template>
<script>
import loader from '@/ux-components/loader/loader.vue';
import modal from '@/digital-components/modal/modal.vue';
export default {
name: 'cancel-claim-modal',
components: {
loader,
modal
},
emits: ['cancel-claim-confirmation', 'return-to-claim'],
data() {
return {
isLoaderDisplayed: false,
isModalOpened: false
};
},
@ -65,9 +59,6 @@ export default {
openModal() {
this.$refs.cancelClaimModal.openModal();
},
removeLoader() {
this.isLoaderDisplayed = false;
},
setModalStatus(isOpened) {
this.isModalOpened = isOpened;
},

View file

@ -76,7 +76,6 @@ function setupMocks({
wrapper.vm.$router.navigateWithSpinner = jest.fn();
wrapper.vm.navigateBack = baseMixin.methods.navigateBack;
wrapper.vm.$refs.siteFooter.updateButtonText = jest.fn();
wrapper.vm.$refs.siteFooter.removeLoader = jest.fn();
wrapper.vm.$refs.siteFooter.disableForwardButton = jest.fn();
wrapper.vm.$refs.siteFooter.enableForwardAction = jest.fn();
@ -156,7 +155,7 @@ describe('license-plate-lookup.vue', () => {
// Arrange
const mockRegistrationLicensePlate = {
licensePlate: 'BIGTRUCKTEST'
};
};
const { wrapper } = setupMocks({
lookupVinByPlateResponse: {
@ -187,7 +186,7 @@ describe('license-plate-lookup.vue', () => {
// Arrange
const mockRegistrationLicensePlate = {
licensePlate: 'BIGTRUCKTEST2'
};
};
const { wrapper } = setupMocks({
lookupVinByPlateResponse: {

View file

@ -266,8 +266,7 @@ export default {
if (vinLookupResponse.error) {
this.displayVinNotFoundAlert = true;
this.previouslyEnteredCarId = null;
this.$refs.siteFooter.disableForwardButton();
return this.$refs.siteFooter.removeLoader();
return this.$refs.siteFooter.disableForwardButton();
}
// Vehicle found from VIN lookup
@ -275,8 +274,7 @@ export default {
if (!vehicleFromLookup.canSafeliteService) {
this.displayNoServiceAlert = true;
this.$refs.siteFooter.disableForwardButton();
return this.$refs.siteFooter.removeLoader();
return this.$refs.siteFooter.disableForwardButton();
}
// Check if the CarId has changed
@ -299,10 +297,9 @@ export default {
this.isSelectedGlassAvailableForVehicle = await isGlassAvailableForCarId(vehicleFromLookup.carId);
// Update button "Continue with..."
this.$refs.siteFooter
return this.$refs.siteFooter
// eslint-disable-next-line max-len
.updateButtonText(`Continue with ${vehicleFromLookup.year} ${vehicleFromLookup.make} ${vehicleFromLookup.model} ${this.forwardButtonCarStyle}`);
return this.$refs.siteFooter.removeLoader();
}
// Save vehicle, license plate, and registration information

View file

@ -63,7 +63,6 @@ function setupMocks() {
wrapper.vm.$router.navigateWithSpinner = jest.fn();
wrapper.vm.navigateBack = baseMixin.methods.navigateBack;
wrapper.vm.$refs.siteFooter.updateButtonText = jest.fn();
wrapper.vm.$refs.siteFooter.removeLoader = jest.fn();
wrapper.vm.$refs.siteFooter.disableForwardButton = jest.fn();
wrapper.vm.$refs.siteFooter.enableForwardAction = jest.fn();

View file

@ -72,7 +72,6 @@ function setupMocks() {
wrapper.vm.setCmsContent = jest.fn();
wrapper.vm.setCmsContent = baseMixin.methods.setCmsContent;
wrapper.vm.$refs.siteFooter.updateButtonText = jest.fn();
wrapper.vm.$refs.siteFooter.removeLoader = jest.fn();
wrapper.vm.$refs.siteFooter.disableForwardButton = jest.fn();
return { wrapper };
}

View file

@ -232,7 +232,6 @@ export default {
if (this.mainStore.issConfig.enableTPAFlow) {
if (this.mainStore.hasRecalibrationPart) {
this.$refs[TPA_RECAL_MODAL_REF_NAME].openModal();
this.$refs[SITE_FOOTER_REF_NAME].removeLoader();
return;
}
scenario =

View file

@ -426,7 +426,6 @@ export default {
if (partsOrQuestionsResponse.error) {
this.mainStore.setBailout(bailoutMessage.PartsServiceError(partsOrQuestionsResponse.error.data));
window.console.error('Error on retrieving PartsOrQuestions');
this.$refs.siteFooter.removeLoader();
this.hasBailedOut = true;
this.$router.navigate(
this.navigationScenarios.CLICKED_FORWARD_WITH_BAILOUT,

View file

@ -91,7 +91,6 @@ function setupMocks({ pageHeaderWidgetHeaderText = {}, mountOptionsMockData = {}
partQuestionRearWrapper.vm.initializeComponent = glassPartQuestion.methods.initializeComponent;
wrapper.vm.setCmsContent = baseMixin.methods.setCmsContent;
wrapper.vm.$refs.siteFooter.removeLoader = jest.fn();
return { wrapper, apiPromise };
}

View file

@ -194,7 +194,6 @@ export default {
}
// If no parts could be matched, throw an error (isForwardActionDisabled is based off of matchedParts)
if (this.isForwardActionDisabled) {
this.$refs.siteFooter.removeLoader();
throw new Error('Could not match any parts to the selected parts');
}

View file

@ -179,7 +179,6 @@ export default {
this.activeVehicleLookupAlertType = vehicleLookupAlertTypes.NOT_FOUND;
this.mainStore.setBailout(bailoutMessage.vehicleNotFound(this.vin));
this.resetVehicleFromLookup();
this.$refs.siteFooter.removeLoader();
// Temp solution to turn on 'disabled' style on the Continue button
// because the form itself actually passes its client-side validation.
// SSR-189 Scenario #4.
@ -191,7 +190,6 @@ export default {
this.activeVehicleLookupAlertType = vehicleLookupAlertTypes.NO_SERVICE;
this.resetVehicleFromLookup();
this.$refs.siteFooter.disableForwardButton();
this.$refs.siteFooter.removeLoader();
return;
}
@ -218,8 +216,6 @@ export default {
// eslint-disable-next-line max-len
`${this.vehicleFromLookup.year} ${this.vehicleFromLookup.make} ${this.vehicleFromLookup.model} ${this.forwardButtonCarStyle}`;
this.$refs.siteFooter.updateButtonText(`Continue with ${vehicleYearMakeModelStyle}`);
this.$refs.siteFooter.removeLoader();
this.needToLookupVehicle = false;
return null;

View file

@ -87,7 +87,6 @@ function setupMocks({
wrapper.vm.setCmsContent = baseMixin.methods.setCmsContent;
wrapper.vm.getCmsContent = jest.fn().mockImplementation(() => '');
wrapper.vm.$refs.siteFooter.removeLoader = jest.fn();
return { wrapper, apiPromise };
}

View file

@ -332,7 +332,6 @@ export default {
return Promise.resolve();
} catch (e) {
this.displayInvalidZipAlert = true;
this.$refs.siteFooter.removeLoader();
return Promise.reject(e);
}
},
@ -454,11 +453,8 @@ export default {
console.error(`Error on loading session from cookie ${error}`);
this.startNewReferral();
} finally {
this.$refs.continueModal.removeLoader();
this.$refs.continueModal.closeModal();
}
} else {
this.$refs.continueModal.removeLoader();
}
},
startNewReferral() {

View file

@ -8,14 +8,9 @@
$accent-fill: #e6f1f3; // Calendar background
$accent-color: #09748b;
$link: #09748b;
$button-color: #a9e3e9;
$button-text-color: #181643;
$svg-fill-color: '%2309748b'; // Color of calendar icon. Place HEX code *after* %23
$progress-bar-color: #181643;
//Variables
--iss-loader-color: #{$button-text-color};
svg,
.modal-text {
fill: $accent-color;
@ -30,51 +25,6 @@
a.new-window-link {
color: $link;
}
.btn {
&.btn-override[aria-disabled="false"]:not(.form-test-invalid) {
&.btn-primary {
background: $button-color;
color: $button-text-color;
}
&:focus-visible {
background: $button-color;
color: $button-text-color;
box-shadow: 0 0 0 3px $white, 0 0 0 5.5px $button-color;
}
}
}
}
&.modal-open {
.modal {
.modal-body {
.btn {
&.btn-override[aria-disabled="false"]:not(.form-test-invalid) {
&.btn-primary {
background: $button-color;
color: $button-text-color;
}
&:focus-visible {
background: $button-color;
color: $button-text-color;
box-shadow: 0 0 0 3px $white, 0 0 0 5.5px $button-color;
}
}
}
}
.modal-footer {
.btn:not(.navigation-link) {
background: $button-color;
color: $button-text-color;
}
}
}
}
.progress-bar-container {

View file

@ -1,5 +1,5 @@
@import "@/styles/ux-variables-svg-strings.scss";
html {
.has-error {
@ -202,24 +202,9 @@ html {
}
.form-test-invalid {
// Disable Gray coloring to match Heritage
&.btn.btn-primary {
//color: $gray-600;
//background: $gray-200;
cursor: pointer;
pointer-events: all;
}
//&.btn.btn-primary:hover,
//&.btn.btn-primary:focus {
//color: $gray-600;
//background: $gray-200;
//box-shadow: none;
//}
//&.btn.btn-primary:focus-visible {
// box-shadow: 0 0 0 3px $white, 0 0 0 5.5px $gray-700;
//}
}
}

View file

@ -1,6 +1,5 @@
import { shallowMount } from '@vue/test-utils';
import { getMountOptions } from '@/helpers/unit-test-helper.js';
import { nextTick } from 'vue';
import buttonMain from '@/ux-components/button-main/button-main.vue';
/** @ignore */
@ -48,27 +47,4 @@ describe('buttonMain.vue', () => {
// Expect
expect(button.attributes()['aria-disabled']).toEqual('true');
});
it('Should return loader position', async () => {
// Act
const wrapper = shallowMount(
buttonMain,
setupMocks({
propsData: {
loaderPosition: 'right',
loaderEnabled: true
}
})
);
// Assert
wrapper.vm.clicked();
await nextTick();
const loader = wrapper.find('loader-stub');
expect(loader.attributes('class')).toContain('right');
});
});

View file

@ -5,25 +5,15 @@
:class="[
isPrimary ? 'btn-primary' : 'btn-secondary',
isFloat ? 'float-end' : '',
isLoaderDisplayed ? 'has-loader' : '',
]"
@click="clicked">
<span class="m-0">{{ buttonText }}</span>
<loader
v-if="isLoaderDisplayed && !suppressLoader"
class="ms-2"
:class="[loaderPosition]" />
</button>
</template>
<script>
import loader from '@/ux-components/loader/loader.vue';
export default {
name: 'button-main',
components: {
loader
},
props: {
isPrimary: Boolean,
buttonText: String,
@ -33,23 +23,11 @@ export default {
suppressLoader: Boolean
},
emits: ['click-event'],
data() {
return {
isLoaderDisplayed: false
};
},
methods: {
removeLoader() {
this.isLoaderDisplayed = false;
},
clicked() {
if (!this.isDisabled) {
this.isLoaderDisplayed = true;
this.$emit('click-event');
}
},
resetButtonStyle() {
this.isLoaderDisplayed = false;
}
}
};
@ -98,10 +76,6 @@ $button-width-heritage: 9.0625rem; // 145px
cursor: pointer;
pointer-events: all;
}
&.has-loader {
color: $white;
background: $blue-700;
}
&.delay {
// fixes flicker while transitioning between states
transition: background 0s 0s ease-in-out;
@ -136,10 +110,6 @@ $button-width-heritage: 9.0625rem; // 145px
cursor: pointer;
pointer-events: all;
}
&.has-loader {
color: $white;
@include blue-gradient;
}
&.delay {
// fixes flicker while transitioning between states
transition: background 0s 0s ease-in-out;

View file

@ -45,97 +45,6 @@ describe('modal-button-main.vue', () => {
expect(button.attributes()['aria-disabled']).toEqual('true');
});
it('Should return loader color', async () => {
// Arrange
const wrapper = shallowMount(
modalButtonMain,
setupMocks({
propsData: {
loaderColor: 'blue',
loaderEnabled: true
}
})
);
// Act
wrapper.vm.clicked();
await nextTick();
// Assert
const loader = wrapper.find('loader-stub');
expect(loader.attributes('class')).toContain('blue');
});
it('Should return loader position', async () => {
// Arrange
const wrapper = shallowMount(
modalButtonMain,
setupMocks({
propsData: {
loaderPosition: 'right',
loaderEnabled: true
}
})
);
// Act
wrapper.vm.clicked();
await nextTick();
// Assert
const loader = wrapper.find('loader-stub');
expect(loader.attributes('class')).toContain('right');
});
it("Should set 'isLoaderDisplayed' to false when calling 'removeLoader'", async () => {
// Arrange
const wrapper = shallowMount(
modalButtonMain,
setupMocks({
propsData: {
loaderPosition: 'right',
loaderEnabled: true
}
})
);
wrapper.setData({
isLoaderDisplayed: true
});
// Act
wrapper.vm.removeLoader();
await nextTick();
// Assert
expect(wrapper.vm.isLoaderDisplayed).toBe(false);
});
it("Should set 'isLoaderDisplayed' to false when calling 'resetButtonStyle'", async () => {
// Arrange
const wrapper = shallowMount(
modalButtonMain,
setupMocks({
propsData: {
loaderPosition: 'right',
loaderEnabled: true
}
})
);
wrapper.setData({
isLoaderDisplayed: true
});
// Act
wrapper.vm.resetButtonStyle();
await nextTick();
// Assert
expect(wrapper.vm.isLoaderDisplayed).toBe(false);
});
it("Should emit 'click-event' event when clicking if the button is enabled", async () => {
// Arrange
const wrapper = shallowMount(

View file

@ -6,25 +6,16 @@
:class="[
isPrimary ? 'btn-primary' : 'btn-secondary',
isFloat ? 'float-end' : '',
isLoaderDisplayed ? 'has-loader' : '',
]"
@click="clicked">
<span class="m-0">{{ buttonText }}</span>
<loader
v-if="isLoaderDisplayed && !suppressLoader"
class="ms-2"
:class="[loaderColor, loaderPosition]" />
</button>
</template>
<script>
import loader from '@/ux-components/loader/loader.vue';
export default {
name: 'modal-button-main',
components: {
loader
},
props: {
isPrimary: Boolean,
buttonText: String,
@ -35,15 +26,7 @@ export default {
suppressLoader: Boolean
},
emits: ['click-event'],
data() {
return {
isLoaderDisplayed: false
};
},
methods: {
removeLoader() {
this.isLoaderDisplayed = false;
},
clicked() {
this.pushEventToGA(
this.$route.query[this.queryStrings.ISS_PAGE],
@ -52,12 +35,8 @@ export default {
true
);
if (!this.isDisabled) {
this.isLoaderDisplayed = true;
this.$emit('click-event');
}
},
resetButtonStyle() {
this.isLoaderDisplayed = false;
}
}
};
@ -97,11 +76,6 @@ export default {
cursor: pointer;
pointer-events: all;
}
&.has-loader {
color: $white;
background: $blue-700;
pointer-events: none;
}
&.delay {
// fixes flicker while transitioning between states
transition: background 0s 0s ease-in-out;
@ -138,11 +112,6 @@ export default {
cursor: pointer;
pointer-events: all;
}
&.has-loader {
color: $white;
@include blue-gradient;
pointer-events: none;
}
&.delay {
// fixes flicker while transitioning between states
transition: background 0s 0s ease-in-out;