190 lines
5.2 KiB
Vue
190 lines
5.2 KiB
Vue
<template>
|
|
<div id="product-modal" ref="modal" class="modal fade" tabindex="-1">
|
|
<div class="modal-dialog modal-dialog-centered modal-dialog-scrollable modal-xxl modal-fullscreen-md-down">
|
|
<div class="modal-content">
|
|
<div class="modal-header position-relative">
|
|
<h5
|
|
v-if="product"
|
|
:class="{ ...{
|
|
'product-title': true,
|
|
'fw-bold text-capitalize text-center rounded mt-4 py-3 px-4 flex-grow-1 mx-5 px-5': true,
|
|
|
|
'fs-1 mt-2 mt-md-5': true,
|
|
}, ... rangeFont(range.font_id)}"
|
|
>
|
|
{{ transField(product, 'name') }}
|
|
</h5>
|
|
<button
|
|
type="button"
|
|
class="btn-close me-4 position-absolute end-0 top-0"
|
|
:aria-label="t('close_products_modal')"
|
|
:title="t('close_products_modal')"
|
|
data-bs-toggle="tooltip"
|
|
data-bs-dismiss="modal"
|
|
/>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="row">
|
|
<div class="col text-center">
|
|
<img
|
|
v-if="product"
|
|
class="img-fluid"
|
|
:src="`/data/${product.picture}`"
|
|
:alt="t('products_logo', {'product_name': transField(product, 'name')})"
|
|
:title="t('products_logo', {'product_name': transField(product, 'name')})"
|
|
data-bs-toggle="tooltip"
|
|
>
|
|
</div>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col pt-5 ps-md-4 description">
|
|
<div v-if="product" v-sane-html="transField(product, 'description')" class="p-md-3 my-md-5" />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts">
|
|
|
|
import { Modal } from "bootstrap";
|
|
import DOMPurify from "dompurify";
|
|
import type { DirectiveBinding, PropType } from "vue";
|
|
import { defineComponent } from "vue";
|
|
import ToolboxHelper from "~/classes/ToolboxHelper";
|
|
import { Tooltips } from "~/vueModules/bsTooltips";
|
|
|
|
const saneHtml = {
|
|
mounted: (el: HTMLElement, binding: DirectiveBinding) => {
|
|
el.innerHTML = DOMPurify.sanitize(binding.value);
|
|
},
|
|
};
|
|
|
|
export default defineComponent({
|
|
name: "ProductDescriptionModal",
|
|
directives: {
|
|
saneHtml,
|
|
},
|
|
props: {
|
|
show: {
|
|
type: Boolean,
|
|
required: true,
|
|
},
|
|
range: {
|
|
type: Object as PropType<TypeRange>,
|
|
required: true,
|
|
},
|
|
product: {
|
|
type: Object as PropType<TypeProduct>|null,
|
|
nullable: true,
|
|
default: undefined,
|
|
required: false,
|
|
}
|
|
},
|
|
emits: [
|
|
"closed", "openned"
|
|
],
|
|
data(): {
|
|
modal: Modal|null;
|
|
tooltips: Tooltips|null;
|
|
} {
|
|
return {
|
|
modal: null,
|
|
tooltips: null
|
|
};
|
|
},
|
|
watch: {
|
|
show() {
|
|
this.$nextTick(() => {
|
|
if(this.show) {
|
|
this.modal?.show();
|
|
} else {
|
|
this.modal?.hide();
|
|
}
|
|
});
|
|
}
|
|
},
|
|
mounted() {
|
|
this.$nextTick(() => {
|
|
const modal = this.$refs.modal as HTMLElement;
|
|
modal.addEventListener("shown.bs.modal", () => {
|
|
this.tooltips = Tooltips.make({type:"parent", parentSelector: "#product-modal"});
|
|
this.$emit("openned");
|
|
});
|
|
modal.addEventListener("hidden.bs.modal", () => {
|
|
this.tooltips?.closeBootstrapTooltip();
|
|
this.$emit("closed");
|
|
});
|
|
this.modal = Modal.getOrCreateInstance(modal);
|
|
});
|
|
},
|
|
beforeUnmount() {
|
|
this.tooltips?.closeBootstrapTooltip();
|
|
this.modal?.hide();
|
|
},
|
|
methods: {
|
|
t(text: string, params: Record<string,string> = {}, localeToUse: string|null = null): string {
|
|
return ToolboxHelper.trans(text, params, localeToUse);
|
|
},
|
|
transField(model: Typei18nModel, field: Typei18nFieldList) {
|
|
return ToolboxHelper.getTranslatableField(model, field);
|
|
},
|
|
rangeFont(fontId: number) {
|
|
const font = useAppStore().getFont(fontId);
|
|
const out: Map<string, boolean> = new Map<string, boolean>();
|
|
if(font) {
|
|
out.set(`f-${font.font_name}`, true);
|
|
}
|
|
return Object.fromEntries(out.entries());
|
|
},
|
|
},
|
|
});
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
@import "bootstrap/scss/functions";
|
|
@import "bootstrap/scss/variables";
|
|
@import "bootstrap/scss/variables-dark";
|
|
@import "bootstrap/scss/maps";
|
|
@import "bootstrap/scss/mixins";
|
|
@import "bootstrap/scss/vendor/rfs";
|
|
|
|
.btn-close {
|
|
@include media-breakpoint-up(md) {
|
|
@include rfs(1.5em, padding-bottom);
|
|
@include rfs(1.3em, font-size);
|
|
}
|
|
@include media-breakpoint-up(xxl) {
|
|
@include rfs(2em, padding-bottom);
|
|
@include rfs(1.5em, font-size);
|
|
}
|
|
}
|
|
|
|
.product-title {
|
|
@include rfs(1.4rem, font-size);
|
|
@include rfs(1rem, padding-bottom);
|
|
|
|
@include media-breakpoint-up(md) {
|
|
@include rfs(1.8rem, font-size);
|
|
@include rfs(3rem, padding-bottom);
|
|
}
|
|
@include media-breakpoint-up(xxl) {
|
|
@include rfs(2.8rem, font-size);
|
|
@include rfs(6rem, padding-bottom);
|
|
}
|
|
}
|
|
|
|
.description {
|
|
@include rfs(1em, font-size);
|
|
@include media-breakpoint-up(md) {
|
|
@include rfs(1.1em, font-size);
|
|
@include rfs(1.1em, padding-bottom);
|
|
}
|
|
@include media-breakpoint-up(xxl) {
|
|
@include rfs(1.15em, font-size);
|
|
@include rfs(1.35em, padding-bottom);
|
|
}
|
|
}
|
|
</style>
|