269 lines
8 KiB
Vue
269 lines
8 KiB
Vue
<template>
|
|
<div
|
|
class="modal fade"
|
|
id="manualResponseModal"
|
|
ref="manualResponseModal"
|
|
tabindex="-1"
|
|
aria-labelledby="manualResponseModalLabel"
|
|
aria-hidden="true"
|
|
>
|
|
<div class="modal-dialog modal-dialog-centered modal-dialog-scrollable modal-lg">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<p
|
|
class="modal-title fs-5"
|
|
id="manualResponseModalLabel"
|
|
>
|
|
{{ trans.methods.__('Votre réponse au client') }}
|
|
</p>
|
|
<button
|
|
type="button"
|
|
class="btn-close"
|
|
data-bs-dismiss="modal"
|
|
aria-label="Close"
|
|
/>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="row w-100 mx-auto">
|
|
<div class="col-12">
|
|
<label
|
|
for="template"
|
|
class="col-form-label pt-0"
|
|
>
|
|
<b>{{ trans.methods.__('Choisir un modèle de réponse') }}</b>
|
|
</label>
|
|
<SearchBelongsToDropdown
|
|
id="template"
|
|
name="template_id"
|
|
:label="trans.methods.__('Choisir un modèle de réponse')"
|
|
:model="claimModel"
|
|
:modelselected="selectedTemplate as VselectOption"
|
|
targetclass="App\Models\ClaimMailTemplate"
|
|
:modellistpaginate="claimTemplateModels"
|
|
:constructedroute="getClaimTemplatePaginateRoute()"
|
|
fieldname="label"
|
|
:multiple="false"
|
|
:required="true"
|
|
:disabled="loading"
|
|
:placeholder="trans.methods.__('Rechercher un template', { model: trans.methods.__('models.classes.claim_mail_templates') })"
|
|
@selected-value-changed="changeTemplate"
|
|
/>
|
|
</div>
|
|
<div class="col-12">
|
|
<label
|
|
for="message"
|
|
class="col-form-label"
|
|
>
|
|
<b>{{ trans.methods.__('Votre message') }} *</b>
|
|
</label>
|
|
<CkEditorComponent
|
|
name="content"
|
|
:dbtext="message"
|
|
:required="true"
|
|
@input="message = $event"
|
|
/>
|
|
<small class="text-danger m-0">
|
|
{{ errors.methods.parseValidationInput('content', allErrors) }}
|
|
</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button
|
|
type="button"
|
|
class="btn btn-secondary"
|
|
data-bs-dismiss="modal"
|
|
>
|
|
{{ trans.methods.__('Fermer') }}
|
|
</button>
|
|
<button
|
|
type="button"
|
|
class="btn btn-primary"
|
|
data-bs-tooltip="tooltip"
|
|
:title="trans.methods.__('Répondre au client')"
|
|
@click="sendResponse()"
|
|
:disabled="loading"
|
|
>
|
|
<div
|
|
v-show="loading"
|
|
class="spinner-border spinner-border-sm"
|
|
role="status"
|
|
>
|
|
<span class="visually-hidden">{{ trans.methods.__('Chargement...') }}</span>
|
|
</div>
|
|
<div v-show="!loading">
|
|
{{ trans.methods.__('Envoyer votre réponse au client') }}
|
|
</div>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { computed, useAttrs, onMounted, ref, watch } from "vue";
|
|
import type { PropType } from "vue";
|
|
import { Modal } from "bootstrap";
|
|
import errors from "./../../modules/errors";
|
|
import trans from "./../../modules/trans";
|
|
import route from "./../../modules/route";
|
|
import { Tooltips } from "./../../modules/tooltips";
|
|
import CkEditorComponent from "./CkEditorComponent.vue";
|
|
import SearchBelongsToDropdown from "./SearchBelongsToDropdownComponent.vue";
|
|
|
|
defineOptions({
|
|
name: "ClaimWrapperComponent",
|
|
});
|
|
|
|
// * ATTRIBUTES
|
|
const attrs = useAttrs();
|
|
|
|
// * EMITS
|
|
const emits = defineEmits<{
|
|
(e: "answerSent", value: Array<LaravelModel & LaravelModelUserRelation>): void;
|
|
}>();
|
|
|
|
// * PROPS
|
|
const props = defineProps({
|
|
claimModel: {
|
|
type: Object as PropType<LaravelModel & LaravelModelClaimRelations>,
|
|
default: () => { return []; },
|
|
},
|
|
claimTemplateModels: {
|
|
type: Object as PropType<LaravelPaginator>,
|
|
default: () => { return {}; },
|
|
},
|
|
message: {
|
|
type: String,
|
|
default: "",
|
|
},
|
|
selectedTemplate: {
|
|
type: Object as PropType<LaravelModel|null>,
|
|
default: null,
|
|
},
|
|
loading: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
isManualResponseType: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
allErrors: {
|
|
type: Object as PropType<LaravelValidationErrors>,
|
|
default: () => { return {}; },
|
|
},
|
|
});
|
|
|
|
// * REFS
|
|
const manualResponseModal = ref<HTMLDivElement|null>(null);
|
|
|
|
// * DATA
|
|
const claimModel = ref<LaravelModel & LaravelModelClaimRelations>(props.claimModel);
|
|
const claimTemplateModels = ref<LaravelPaginator>(props.claimTemplateModels);
|
|
const bootstrapModal = ref<Modal|null>(null);
|
|
const message = ref<string>(props.message);
|
|
const selectedTemplate = ref<LaravelModel|null>(props.selectedTemplate);
|
|
const loading = ref<boolean>(props.loading);
|
|
const isManualResponseType = ref<boolean>(props.isManualResponseType);
|
|
const allErrors = ref<LaravelValidationErrors>(props.allErrors);
|
|
const tooltips = ref<Tooltips|null>(null);
|
|
|
|
// * COMPUTED
|
|
const isUsedWithProps = computed<boolean>(() => attrs.json === undefined);
|
|
|
|
// * LIFECYCLE
|
|
onMounted((): void => {
|
|
const json = String(attrs.json ?? "{}"),
|
|
data = JSON.parse(json);
|
|
if (!isUsedWithProps.value) {
|
|
claimModel.value = data.claimModel;
|
|
claimTemplateModels.value = data.claimTemplateModels;
|
|
message.value = data.message;
|
|
selectedTemplate.value = data.selectedTemplate;
|
|
loading.value = data.loading;
|
|
isManualResponseType.value = data.isManualResponseType;
|
|
allErrors.value = data.allErrors;
|
|
}
|
|
bootstrapModal.value = new Modal("#manualResponseModal", {});
|
|
initTooltips();
|
|
});
|
|
|
|
// * WATCHERS
|
|
watch(props, () => {
|
|
isManualResponseType.value = props.isManualResponseType;
|
|
if (isManualResponseType.value) {
|
|
bootstrapModal.value?.show();
|
|
}
|
|
});
|
|
|
|
/**
|
|
* Change the template of the content.
|
|
* @param VselectOption|VselectOption[]|null templateModel
|
|
* @return void
|
|
*/
|
|
function changeTemplate(templateModel: VselectOption|VselectOption[]|null): void {
|
|
if (templateModel !== null) {
|
|
selectedTemplate.value = templateModel as LaravelModel;
|
|
message.value = String(selectedTemplate.value.content);
|
|
allErrors.value = {};
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Send the manual response.
|
|
* @return void
|
|
*/
|
|
function sendResponse(): void {
|
|
loading.value = true;
|
|
window.axios
|
|
.post(route.methods.getRoute("bo.claims.answer", {
|
|
CLAIMID: String(claimModel.value.id),
|
|
}), {
|
|
claim_id: claimModel.value.id,
|
|
content: message.value,
|
|
})
|
|
.then((reponse) => {
|
|
message.value = "";
|
|
selectedTemplate.value = null;
|
|
allErrors.value = {};
|
|
loading.value = false;
|
|
emits("answerSent", reponse.data);
|
|
bootstrapModal.value?.hide();
|
|
})
|
|
.catch((e) => {
|
|
loading.value = false;
|
|
allErrors.value = e.response?.data?.errors ?? {};
|
|
errors.methods.ajaxErrorHandler(e);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Return the claim template route.
|
|
* @return string
|
|
*/
|
|
function getClaimTemplatePaginateRoute(): string {
|
|
const targetRoute = "bo.claim_mail_templates.json-paginate";
|
|
const fetchMessageRoute = route.methods.route(targetRoute, {
|
|
BRANDID: String(claimModel.value.brand.id),
|
|
});
|
|
if (!fetchMessageRoute) {
|
|
throw new Error(`Undefined ${targetRoute}`);
|
|
}
|
|
return fetchMessageRoute + "?targetModel=App\\Models\\ClaimMailTemplate&page=1&paginate=5&fieldName=label";
|
|
}
|
|
|
|
/**
|
|
* Initialise all tooltips in the component.
|
|
* @return void
|
|
*/
|
|
function initTooltips(): void {
|
|
setTimeout(() => {
|
|
tooltips.value = Tooltips.make({
|
|
type: "dom",
|
|
elements: manualResponseModal.value!.querySelectorAll("[data-bs-tooltip=\"tooltip\"]")
|
|
});
|
|
}, 500);
|
|
}
|
|
</script>
|