Un-sticky site header.

This commit is contained in:
Bryan Mauger 2023-04-10 14:08:14 -04:00
parent b96216a8ea
commit e9c65f57c0
3 changed files with 243 additions and 206 deletions

View file

@ -1,34 +1,43 @@
<template> <template>
<div :class="`page-container-grouped-styles questions-page`"> <div :class="`page-container-grouped-styles questions-page`">
<loadingModal ref="loadingModal" /> <div class="fade-on-route-transition position-relative">
<siteHeader cmsWidgetName="SiteHeaderWidget" /> <loadingModal ref="loadingModal" />
<div class="fade-on-route-transition sub-container overflow-scroll"> <siteHeader cmsWidgetName="SiteHeaderWidget" />
<vehicleBanner class="mb-3" cmsWidgetName="VehicleBannerWidget" :displayGenericVehicleImage="false" /> <div class="select-car">
<siteSubHeader cmsWidgetName="SiteSubHeaderWidget" /> <div class="container-fluid pb-2">
<alert <div class="row px-3">
ref="alertFewMoreQuestions" <div class="col">
cmsWidgetName="alertWidget" <div class="select-car-form rounded">
class="m-5" <vehicleBanner class="mb-3" cmsWidgetName="VehicleBannerWidget" :displayGenericVehicleImage="false" />
alertClass="alert-warning" <siteSubHeader cmsWidgetName="SiteSubHeaderWidget" />
:manualHeadline="alertFewMoreQuestionsHeader" <alert
:manualCopy="alertFewMoreQuestionsCopy" ref="alertFewMoreQuestions"
v-bind:isDismissible="false" /> cmsWidgetName="alertWidget"
<div v-for="(questionsDatum, i) in questionsData" :key="questionsDatum.key"> alertClass="alert-warning"
<questionChain :manualHeadline="alertFewMoreQuestionsHeader"
ref="questionChain" :manualCopy="alertFewMoreQuestionsCopy"
v-model="selectedAnswers[questionsDatum.answerKey]" v-bind:isDismissible="false" />
:questionData="questionsDatum.questions" <div v-for="(questionsDatum, i) in questionsData" :key="questionsDatum.key">
:index="i" <questionChain
v-if="showThisQuestionChain(questionsDatum, i)" ref="questionChain"
:answerKey="questionsDatum.answerKey" v-model="selectedAnswers[questionsDatum.answerKey]"
:validationRules="validationRules" /> :questionData="questionsDatum.questions"
:index="i"
v-if="showThisQuestionChain(questionsDatum, i)"
:answerKey="questionsDatum.answerKey"
:validationRules="validationRules" />
</div>
<siteFooter
ref="siteFooter"
cmsWidgetName="SiteFooterWidget"
:isForwardActionDisabled="!isMetaValid"
@back-clicked="handleBackButtonAction"
@ForwardClicked="handleForwardButtonAction" />
</div>
</div>
</div>
</div>
</div> </div>
<siteFooter
ref="siteFooter"
cmsWidgetName="SiteFooterWidget"
:isForwardActionDisabled="!isMetaValid"
@back-clicked="handleBackButtonAction"
@ForwardClicked="handleForwardButtonAction" />
</div> </div>
</div> </div>
</template> </template>
@ -94,11 +103,20 @@ export default {
}; };
</script> </script>
<style lang="scss"> <style lang="scss" scoped>
.overflow-scroll { .fade-on-route-transition {
height: calc(100% - 180px); margin-bottom: 100px;
overflow-x: hidden !important; }
} .page-container-grouped-styles {
//height: calc(100% - 80px);
overflow: auto;
}
.modal-open {
.page-container-grouped-styles {
overflow: hidden;
}
}
.questions-page { .questions-page {
.question-text { .question-text {
margin-bottom: 0.5rem; margin-bottom: 0.5rem;

View file

@ -78,7 +78,7 @@ export default {
show() { show() {
this.currentFooterAndHeaderHeight = this.getFooterInfoBoxHeight() + 72; this.currentFooterAndHeaderHeight = this.getFooterInfoBoxHeight() + 72;
this.isActive = true; this.isActive = true;
document.querySelector('.fade-on-route-transition').scrollTo({ document.querySelector('.page-container-grouped-styles').scrollTo({
top: 0, behavior: 'instant' top: 0, behavior: 'instant'
}); });
}, },

View file

@ -1,43 +1,53 @@
<template> <template>
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm"> <Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm">
<div class="page-container-grouped-styles vehicle-parts small-question-text"> <div class="page-container-grouped-styles">
<siteHeader ref="siteHeader" cmsWidgetName="SiteHeaderWidget" /> <div class="fade-on-route-transition position-relative">
<div class="fade-on-route-transition sub-container overflow-scroll px-5"> <siteHeader cmsWidgetName="SiteHeaderWidget" />
<vehicleBanner <div class="select-car">
class="mb-3" <div class="container-fluid pb-2">
ref="vehicleBanner" <div class="row px-3">
cmsWidgetName="VehicleBannerWidget" <div class="col">
:displayGenericVehicleImage="false" /> <div class="select-car-form rounded">
<siteSubHeader ref="siteSubHeader" cmsWidgetName="SiteSubHeaderWidget" /> <vehicleBanner
<div class="prevent-squish my-5"> class="mb-3"
<div class="row"> ref="vehicleBanner"
<div class="col"> cmsWidgetName="VehicleBannerWidget"
<alert :displayGenericVehicleImage="false" />
class="rounded border-0 shadow-sm" <siteSubHeader ref="siteSubHeader" cmsWidgetName="SiteSubHeaderWidget" />
alertClass="alert-warning" <div class="prevent-squish my-5">
cmsWidgetName="AlertWidget" <div class="row">
:isDismissible="false" <div class="col">
id="vehicle-parts-alert" /> <alert
class="rounded border-0 shadow-sm"
alertClass="alert-warning"
cmsWidgetName="AlertWidget"
:isDismissible="false"
id="vehicle-parts-alert" />
</div>
</div>
</div>
<div v-for="(item, i) in PartsOrQuestions" :key="i">
<!-- Render horizontal lines if there is multi-glass (aka if i > 0) -->
<hr v-if="i > 0" />
<glassPartQuestion
:ref="`${RefPrefix}-${item.glassLocation}-${item.glassName}`"
v-model="selectedGlassParts[item.glassLocation + '-' + item.glassName]"
:glassLocation="item.glassLocation"
:glassName="item.glassName"
:colorAnswers="item.colorAnswers"
:alreadyPopulatedPartsData="alreadyPopulatedPartsData" />
</div>
<siteFooter
cmsWidgetName="SiteFooterWidget"
ref="siteFooter"
:isForwardActionDisabled="isForwardActionDisabled"
@backClicked="navigateBack"
@ForwardClicked="forwardButtonAction" />
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
<div v-for="(item, i) in PartsOrQuestions" :key="i">
<!-- Render horizontal lines if there is multi-glass (aka if i > 0) -->
<hr v-if="i > 0" />
<glassPartQuestion
:ref="`${RefPrefix}-${item.glassLocation}-${item.glassName}`"
v-model="selectedGlassParts[item.glassLocation + '-' + item.glassName]"
:glassLocation="item.glassLocation"
:glassName="item.glassName"
:colorAnswers="item.colorAnswers"
:alreadyPopulatedPartsData="alreadyPopulatedPartsData" />
</div>
<siteFooter
cmsWidgetName="SiteFooterWidget"
ref="siteFooter"
:isForwardActionDisabled="isForwardActionDisabled"
@backClicked="navigateBack"
@ForwardClicked="forwardButtonAction" />
</div> </div>
</div> </div>
</Form> </Form>
@ -80,152 +90,161 @@ export default {
// Glass Part Question dynamic component // Glass Part Question dynamic component
Object.keys(vm.$refs) Object.keys(vm.$refs)
.filter((r) => r.includes(vm.RefPrefix) && vm.$refs[r][0] !== undefined) .filter((r) => r.includes(vm.RefPrefix) && vm.$refs[r][0] !== undefined)
.forEach((c) => .forEach((c) =>
vm.$refs[c][0].initializeComponent({ vm.$refs[c][0].initializeComponent({
ColorQuestionWidget: resultMap.cmsContent.ColorQuestionWidget, ColorQuestionWidget: resultMap.cmsContent.ColorQuestionWidget,
FeatureQuestionWidget: resultMap.cmsContent.FeatureQuestionWidget, FeatureQuestionWidget: resultMap.cmsContent.FeatureQuestionWidget,
}) })
); );
}); });
},
data() {
return {
selectedGlassParts: {},
alertWidgetData: Object,
alreadyPopulatedPartsData: [],
};
},
computed: {
isForwardActionDisabled() {
return (
this.selectedGlassPartNumbers.length !== this.PartsFromApi.partsOrQuestions.length
);
}, },
data() { selectedGlassPartNumbers() {
return { // Compile all selected parts from the page.
selectedGlassParts: {}, const numberArray = [];
alertWidgetData: Object, for (let glassPart of Object.values(this.selectedGlassParts)) {
alreadyPopulatedPartsData: [], if (glassPart?.partNumber) {
}; numberArray.push(glassPart.partNumber);
}
}
return numberArray;
}, },
computed: { PartsOrQuestions() {
isForwardActionDisabled() { const partsData = this.PartsFromApi;
return (
this.selectedGlassPartNumbers.length !== this.PartsFromApi.partsOrQuestions.length
);
},
selectedGlassPartNumbers() {
// Compile all selected parts from the page.
const numberArray = [];
for (let glassPart of Object.values(this.selectedGlassParts)) {
if (glassPart?.partNumber) {
numberArray.push(glassPart.partNumber);
}
}
return numberArray;
},
PartsOrQuestions() {
const partsData = this.PartsFromApi;
// Map API result data, to vehicle-parts data structure // Map API result data, to vehicle-parts data structure
const mappedData = partsData.partsOrQuestions.map((g) => { const mappedData = partsData.partsOrQuestions.map((g) => {
return { return {
glassName: g.glassName, glassName: g.glassName,
glassLocation: g.glassLocation, glassLocation: g.glassLocation,
colorAnswers: g.parts?.reduce((arr, p) => { colorAnswers: g.parts?.reduce((arr, p) => {
arr.push({ arr.push({
ColorAnswerText: p.color, ColorAnswerText: p.color,
FeatureAnswers: [ FeatureAnswers: [
{ {
FeatureAnswerText: FeatureAnswerText:
p.description === "" ? p.color : p.description, p.description === "" ? p.color : p.description,
PartNumber: p.partNumber, PartNumber: p.partNumber,
}, },
], ],
});
return arr;
}, []),
};
});
return mappedData;
},
PartsFromApi() {
return this.mainStore.pageData(issPageValues.VEHICLE_PARTS);
},
RefPrefix() {
return "partQuestion";
},
},
methods: {
arePagePrerequisitesValid() {
// Check if isRepair is populated and if the pageData we need is here (Parts data)
return (
this.mainStore.damage.isRepair != null &&
this.mainStore.pageData(issPageValues.VEHICLE_PARTS) &&
Object.keys(this.mainStore.pageData(issPageValues.VEHICLE_PARTS)).length !== 0
);
},
async forwardButtonAction() {
const matchedParts = [];
// Match them to the parts from the API.
for (let [key, value] of Object.entries(this.PartsFromApi.partsOrQuestions)) {
for (let [partKey, partValue] of Object.entries(value.parts)) {
const currentPart = this.PartsFromApi.partsOrQuestions[key].parts[partKey];
const isMatched = this.selectedGlassPartNumbers.some(
(p) => p === currentPart.partNumber
);
if (isMatched) {
matchedParts.push({
glassLocation: value.glassLocation,
glassName: value.glassName,
parts: [currentPart],
});
}
}
}
// 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");
}
await this.mainStore.resetMoldingAndCapabilityQuestionAnswersIfNeeded(matchedParts);
this.navigateForward(matchedParts, null);
},
LoadInitialPartsData() {
const partsData = this.PartsFromApi;
this.alreadyPopulatedPartsData =
this.mainStore.lineItems.glassParts === null
? []
: this.mainStore.lineItems.glassParts;
partsData.partsOrQuestions.map((g) => {
// If the part is already populated, use the value from the store and populate the v-model.
Object.keys(this.alreadyPopulatedPartsData).forEach((key) => {
const partNumber = this.alreadyPopulatedPartsData[key].partNumber;
g.parts.forEach((p) => {
if (p.partNumber === partNumber) {
this.selectedGlassParts[g.glassLocation + "-" + g.glassName] = p;
}
}); });
return arr;
}, []),
};
});
return mappedData;
},
PartsFromApi() {
return this.mainStore.pageData(issPageValues.VEHICLE_PARTS);
},
RefPrefix() {
return "partQuestion";
},
},
methods: {
arePagePrerequisitesValid() {
// Check if isRepair is populated and if the pageData we need is here (Parts data)
return (
this.mainStore.damage.isRepair != null &&
this.mainStore.pageData(issPageValues.VEHICLE_PARTS) &&
Object.keys(this.mainStore.pageData(issPageValues.VEHICLE_PARTS)).length !== 0
);
},
async forwardButtonAction() {
const matchedParts = [];
// Match them to the parts from the API.
for (let [key, value] of Object.entries(this.PartsFromApi.partsOrQuestions)) {
for (let [partKey, partValue] of Object.entries(value.parts)) {
const currentPart = this.PartsFromApi.partsOrQuestions[key].parts[partKey];
const isMatched = this.selectedGlassPartNumbers.some(
(p) => p === currentPart.partNumber
);
if (isMatched) {
matchedParts.push({
glassLocation: value.glassLocation,
glassName: value.glassName,
parts: [currentPart],
});
}
}
}
// 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");
}
await this.mainStore.resetMoldingAndCapabilityQuestionAnswersIfNeeded(matchedParts);
this.navigateForward(matchedParts, null);
},
LoadInitialPartsData() {
const partsData = this.PartsFromApi;
this.alreadyPopulatedPartsData =
this.mainStore.lineItems.glassParts === null
? []
: this.mainStore.lineItems.glassParts;
partsData.partsOrQuestions.map((g) => {
// If the part is already populated, use the value from the store and populate the v-model.
Object.keys(this.alreadyPopulatedPartsData).forEach((key) => {
const partNumber = this.alreadyPopulatedPartsData[key].partNumber;
g.parts.forEach((p) => {
if (p.partNumber === partNumber) {
this.selectedGlassParts[g.glassLocation + "-" + g.glassName] = p;
}
}); });
}); });
}, });
},
mounted() {
this.LoadInitialPartsData();
},
components: {
Form,
glassPartQuestion,
siteHeader,
vehicleBanner,
siteSubHeader,
siteFooter,
alert,
}, },
},
mounted() {
this.LoadInitialPartsData();
},
components: {
Form,
glassPartQuestion,
siteHeader,
vehicleBanner,
siteSubHeader,
siteFooter,
alert,
},
}; };
</script> </script>
<style lang="scss"> <style lang="scss" scoped>
.overflow-scroll { .fade-on-route-transition {
height: calc(100% - 180px); margin-bottom: 100px;
overflow-x: hidden !important; }
.page-container-grouped-styles {
//height: calc(100% - 80px);
overflow: auto;
}
.modal-open {
.page-container-grouped-styles {
overflow: hidden;
}
} }
#vehicle-parts-alert { #vehicle-parts-alert {