Merge pull request #1894 from Safelite/CSR-2115-remove-recal-from-cart

Csr 2115 remove recal from cart
This commit is contained in:
chloeherdsafelite 2024-07-09 15:00:57 -04:00 committed by GitHub
commit fd31a38681
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 186 additions and 22 deletions

View file

@ -6,7 +6,7 @@ This public/css folder uses a standalone .scss > .css setup.
From a Terminal window, run the Sass Watch command from the public folder only:
```bash
sass --no-source-map --watch scss:css
sass --watch scss:css
```
This will compile and output .css files (into the public/css folder) that can be consumed by the Payment page.

View file

@ -24,6 +24,7 @@ const errorMessages = {
VIN_FORMAT:
"Invalid VIN. Please make sure that you entered the correct 17-digit, alpha-numeric number. VINs do not contain the letters I, O, or Q",
OPTION_REQUIRED: "Please select an option",
RECAL_ACK_REQUIRED: "Please acknowledge recalibration alert",
VEHICLE_REQUIRED: "Please select a vehicle",
MOBILE_LOCATION_REQUIRED: "Please enter your service address",
DATE_REQUIRED: "Please select a date",

View file

@ -29,11 +29,25 @@ describe("checkbox-question.vue", () => {
expect(input.attributes().name).toEqual("Checkbox");
});
it("Should return checkbox id", async () => {
it("Should return default id when no custom id is specified", async () => {
// Act
const wrapper = shallowMount(checkboxQuestion, {
propsData: {},
mixins: [mockMixin],
});
// Assert
const input = wrapper.find("input");
// Expect
expect(input.attributes().id).not.toBeFalsy();
});
it("Should return custom id when specified", async () => {
// Act
const wrapper = shallowMount(checkboxQuestion, {
propsData: {
buttonID: "Checkbox ID",
customInputId: "Checkbox ID",
},
mixins: [mockMixin],
});

View file

@ -10,32 +10,67 @@
type="checkbox"
aria-checked="false"
:name="checkboxName"
:id="buttonID"
:validationRules="validationRules"
:id="inputId"
:tabindex="tabIndex"
:aria-required="isRequired" />
<p v-html="checkboxLabelCopy" class="m-0"></p>
<textBlock
class="m-0"
:customText="checkboxLabelCopy"
marginTopSizeOverride="0"
typeStyle="small"
@text-link-clicked="bubbleTextBlockClick" />
<span v-if="screenReaderOnlyText" class="sr-only">{{ screenReaderOnlyText }}</span>
</label>
</div>
</template>
<script>
import { useField, validate } from "vee-validate";
import { v4 as uuidv4 } from "uuid";
import textBlock from "@/digital-components/text-block/text-block";
export default {
name: "checkboxQuestion",
computed: {
checkboxLabelCopy() {
return this.getCmsContent(this.cmsWidgetName, "QuestionText");
},
value: {
get: function () {
return this.modelValue;
},
set: function (newValue) {
this.$emit("update:modelValue", newValue);
},
},
},
setup(props) {
const uuid = uuidv4();
const inputId = !props.customInputId ? `input-${uuid}` : props.customInputId;
const fieldOptions = {
initialValue: props.modelValue,
};
const {
value,
errorMessage,
handleBlur,
handleChange,
meta,
validate,
errors,
resetField,
} = useField(inputId, props.validationRules, fieldOptions);
return {
value,
errorMessage,
handleBlur,
handleChange,
validate,
meta,
errors,
resetField,
inputId,
};
},
props: {
customInputId: String,
validationRules: String,
cmsWidgetName: String,
checkboxName: String,
buttonID: String,
@ -48,6 +83,24 @@ export default {
default: false,
},
},
methods: {
bubbleTextBlockClick(event) {
this.$emit("textLinkClicked", event);
},
},
watch: {
modelValue(newValue, oldValue) {
if (this.value !== newValue) {
this.value = newValue;
}
},
value(newValue, oldValue) {
this.$emit("update:modelValue", newValue);
},
},
components: {
textBlock,
},
};
</script>
@ -56,6 +109,7 @@ export default {
.form-check-input {
border: 1px solid $gray-500;
border-radius: 2px;
min-width: 1rem; // Prevent squish
&:checked {
background-size: 125%;
border: 1px solid $blue;

View file

@ -1,9 +1,10 @@
<template>
<div class="cart">
<div class="px-0">
<!-- set class to 'expaned' on line 7 so cart is open on page load. This may be temporary -->
<div
class="row vin-toggle flex align-items-center pt-4"
:class="[isExpanded ? 'expanded' : '']"
:class="[isExpanded ? '' : 'expanded']"
@click="toggleIsExpanded()">
<a
aria-label="expand cart"

View file

@ -47,7 +47,12 @@ describe("payment-method.vue", () => {
function setupMocks() {
store.getters = {
damage: {},
lineItems: [],
lineItems: {
glassParts: [],
supportingItems: [],
vaps: [],
promos: [],
},
order: {
payment: {
isPia: false,
@ -55,6 +60,12 @@ function setupMocks() {
isVerified: true,
},
},
lineItems: {
glassParts: [],
supportingItems: [],
vaps: [],
promos: [],
},
policy: {
currentDeductible: 123,
isNoComp: false,

View file

@ -1,7 +1,7 @@
<template>
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }">
<loadingModal notFullScreen ref="loadingModal" />
<div class="container-fluid">
<div class="container-fluid payment-method">
<div class="row justify-content-center">
<div class="col-md-6">
<funnelHeader cmsWidgetName="FunnelHeaderWidget" ref="funnelHeader" />
@ -46,10 +46,28 @@
v-bind:isDismissible="false" />
</div>
<div v-if="hasRecal && !isInsurance" class="questions-about-service my-5">
<textBlock
cmsWidgetName="QuestionsAboutYourServiceWidget"
justifyText="left"
class="service-questions" />
<textBlock cmsWidgetName="CallOrTextWidget" justifyText="left" />
<hr class="my-5" />
<div class="d-flex flex-row checkbox-group">
<checkboxQuestion
cmsWidgetName="RecalConfirmWidget"
class="mb-5"
isRequired="true"
v-model="isRecalAckOptIn"
validationRules="recal-ack-required"
@text-link-clicked="openModal('RecalModal')" />
</div>
</div>
<paymentMethodQuestion
v-if="isPiaEnabled && totalAmountDue > 0"
v-model="paymentMethodInternalModel"
validationRules="option-required" />
validationRules="payment-method-required" />
<alert
v-if="!isPiaEnabled && totalAmountDue > 0"
@ -66,6 +84,11 @@
buttonSize
@back-clicked="backButtonAction"
@ForwardClicked="forwardButtonAction" />
<contentGroupModal
ref="RecalModal"
cmsWidgetName="RecalModal"
class="recal-modal" />
</div>
</div>
</div>
@ -83,13 +106,20 @@ import cart from "@/fmg-components/cart/cart";
import reviewDropdown from "@/layouts/payment-method/review-dropdown/review-dropdown";
import { submitWorkOrder } from "@/helpers/heritage-integration/order-helper.js";
import alert from "@/ux-components/alert/alert";
import textBlock from "@/digital-components/text-block/text-block";
import checkboxQuestion from "@/digital-components/checkbox-question/checkbox-question";
import contentGroupModal from "@/fmg-components/content-group-modal/content-group-modal";
// Supporting Items
import baseMixin from "@/mixins/base-mixin.js";
import { settleAllPromises } from "@/helpers/layout-helper";
import { storeActions } from "@/constants/store-actions";
import store from "@/store";
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
import {
fetchCmsContentForPage,
doesCopyContainRouterLink,
getRouterLinkRouteFromCopy,
} from "@/helpers/cms-content-helper";
import { paymentMethods } from "@/constants/payment-method-constants";
import { experimentSettings } from "@/constants/experiments";
import {
@ -116,10 +146,14 @@ import { partTypeStrings } from "@/constants/part-type-strings";
import { mapTaxedLineItemsToStoreFormat } from "../../store";
import { coverageStatus } from "@/constants/insurance";
defineRule("option-required", required(errorMessages.OPTION_REQUIRED));
defineRule("payment-method-required", required(errorMessages.OPTION_REQUIRED));
defineRule("recal-ack-required", required(errorMessages.RECAL_ACK_REQUIRED));
export default {
name: "paymentMethod",
props: {
recyclingModalCmsWidgetName: String,
},
async beforeRouteEnter(to, from, next) {
// Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
@ -309,9 +343,15 @@ export default {
availableVaps: [],
paymentMethodInternalModel: this.getPaymentMethodFromStore(),
inactivePromos: this.getInactivePromosFromStore(),
isRecalAckOptIn: false,
};
},
methods: {
doesCopyContainRouterLink,
getRouterLinkRouteFromCopy,
navigateWithScenario(scenarioName) {
this.$router.navigateWithoutSaving(scenarioName, this.$route);
},
arePagePrerequisitesValid() {
// Service Location
const serviceLocation = store.getters.order.serviceLocation;
@ -451,14 +491,12 @@ export default {
this.paymentMethod,
false
);
// save lineitems as they now have salestax added
await this.dispatchStoreAction(
storeActions.SAVE_GLASS_PARTS_SUPPRESSING_STATE_RESETTING,
this.lineItems.glassParts,
false
);
await this.dispatchStoreAction(
storeActions.SAVE_SUPPORTING_ITEMS_SUPPRESSING_STATE_RESETTING,
this.lineItems.supportingItems,
@ -473,7 +511,6 @@ export default {
},
false
);
if (this.paymentMethod == paymentMethods.LATER) {
// this creates the final work order
await submitWorkOrder({ pageNameToLog: "payment-method", submitAfterSave: true });
@ -513,8 +550,20 @@ export default {
hasSubmittedOrder() {
return this.$store.getters.hasSubmittedOrder;
},
openModal(modalName) {
this.$refs[modalName].openModal();
},
},
computed: {
hasRecal() {
const recalLineItem = this.$store.getters.order.lineItems.supportingItems.find(
(lineItem) => lineItem.partType == partTypeStrings.RECALIBRATION
);
if (recalLineItem) {
return true;
}
return false;
},
damageInfo() {
return this.$store.getters.damage;
},
@ -653,11 +702,27 @@ export default {
alert,
paymentMethodQuestion,
reviewDropdown,
textBlock,
checkboxQuestion,
contentGroupModal,
},
};
</script>
<style></style>
<style lang="scss" scoped>
.checkbox-group {
align-items: start;
> * {
margin-top: 0;
}
}
.questions-about-service {
.service-questions {
font-weight: $font-weight-bold;
}
}
.cart {
margin-bottom: 0;
}
@ -665,4 +730,22 @@ export default {
color: $gray-550;
margin: 0;
}
.payment-method {
.recal-modal {
:deep(.modal-body) {
display: flex;
flex-direction: column;
h5 {
text-align: center;
order: 1;
}
p {
order: 3;
}
img {
order: 2;
}
}
}
}
</style>