ldc-crm/resources/ts/bo/components/ClaimManualResponseComponent.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>