501 lines
16 KiB
Vue
501 lines
16 KiB
Vue
<template>
|
|
<table
|
|
ref="claimActions"
|
|
class="table table-hover m-0"
|
|
>
|
|
<tbody>
|
|
<!-- Brand -->
|
|
<tr class="border-bottom">
|
|
<td
|
|
class="align-middle pb-3"
|
|
colspan="2"
|
|
v-if="canParameters.updateBrand"
|
|
>
|
|
<label
|
|
for="brand"
|
|
class="col-form-label"
|
|
>
|
|
<b>{{ trans.methods.__('Modifier la :model', { model: brandLabel }) }} *</b>
|
|
</label>
|
|
<SearchBelongsToDropdown
|
|
id="brand"
|
|
name="brand_id"
|
|
:label="trans.methods.__('Modifier la :model', { model: brandLabel })"
|
|
:model="claimModel"
|
|
targetclass="App\Models\Brand"
|
|
:modellistpaginate="brandModels"
|
|
:modelselected="(selectParameters.brand as VselectOption)"
|
|
:constructedroute="route.methods.getRoute('bo.brands.json-paginate')"
|
|
fieldname="name"
|
|
:multiple="false"
|
|
:required="true"
|
|
:disabled="loading || isTreatedClaim"
|
|
:placeholder="trans.methods.__('Rechercher une :model', { model: brandLabel })"
|
|
@selected-value-changed="setSelectedBrand"
|
|
/>
|
|
<small class="text-danger m-0">
|
|
{{ errors.methods.parseValidationInput('brand_id', allErrors) }}
|
|
</small>
|
|
</td>
|
|
<template v-else>
|
|
<td class="align-middle text-capitalize fw-bold">
|
|
{{ brandLabel }}
|
|
</td>
|
|
<td
|
|
v-if="claimModel.brand"
|
|
class="align-middle"
|
|
>
|
|
{{ selectParameters.brand.name }}
|
|
</td>
|
|
</template>
|
|
</tr>
|
|
<!-- Subject -->
|
|
<tr class="border-bottom">
|
|
<td
|
|
class="align-middle pb-3"
|
|
colspan="2"
|
|
v-if="canParameters.updateSubject"
|
|
>
|
|
<label
|
|
for="brand"
|
|
class="col-form-label"
|
|
>
|
|
<b>{{ trans.methods.__('Modifier le :model', { model: claimsubjectLabel }) }} *</b>
|
|
</label>
|
|
<SearchBelongsToDropdown
|
|
id="subject"
|
|
name="subject_id"
|
|
:label="trans.methods.__('Modifier le :model', { model: claimsubjectLabel })"
|
|
:model="claimModel"
|
|
targetclass="App\Models\ClaimSubject"
|
|
:modellistpaginate="claimSubjectModels"
|
|
:modelselected="(selectParameters.subject as VselectOption)"
|
|
:constructedroute="getClaimSubjectPaginateRoute()"
|
|
fieldname="label"
|
|
:nodeclass="allErrors.subject_id ? 'form-control is-invalid' : ''"
|
|
:multiple="false"
|
|
:required="true"
|
|
:disabled="loading || isTreatedClaim"
|
|
:placeholder="trans.methods.__('Rechercher une :model', { model: claimsubjectLabel })"
|
|
@selected-value-changed="setSelectedSubject"
|
|
/>
|
|
<small class="text-danger m-0">
|
|
{{ errors.methods.parseValidationInput('subject_id', allErrors) }}
|
|
</small>
|
|
</td>
|
|
<template v-else>
|
|
<td class="align-middle text-capitalize fw-bold">
|
|
{{ claimsubjectLabel }}
|
|
</td>
|
|
<td class="align-middle">
|
|
{{ selectParameters.subject?.label }}
|
|
</td>
|
|
</template>
|
|
</tr>
|
|
<!-- Enums (Type, Status, ResponseType) -->
|
|
<tr
|
|
v-for="(enumField, enumFieldIndex) in enumFields"
|
|
:key="enumFieldIndex"
|
|
:class="{'border-0': enumFieldIndex === Object.keys(enumFields).length - 1}"
|
|
>
|
|
<td
|
|
class="align-middle pb-3"
|
|
:class="{'border-0': enumFieldIndex === Object.keys(enumFields).length - 1}"
|
|
colspan="2"
|
|
v-if="enumField.can"
|
|
>
|
|
<label
|
|
:for="enumField.name"
|
|
class="col-form-label"
|
|
>
|
|
<b>{{ trans.methods.__('Modifier le :label', { label: trans.methods.__(`validation.custom.${enumField.name}`) }) }} *</b>
|
|
</label>
|
|
<div
|
|
:key="localVersion"
|
|
class="d-flex justify-content-center align-items-center"
|
|
>
|
|
<select
|
|
:id="enumField.name"
|
|
class="form-select"
|
|
:class="{'is-invalid': errors.methods.parseValidationInput(`${enumField.name}`, allErrors)}"
|
|
:name="enumField.name"
|
|
:aria-describedby="`${enumField.name}Help`"
|
|
required="true"
|
|
role="button"
|
|
:disabled="loading || (enumField.name !== 'status') ? isTreatedClaim : false"
|
|
@change="setSelectedEnum($event, enumField.name)"
|
|
>
|
|
<option
|
|
v-for="(model, modelIndex) in enumField.associatedEnum"
|
|
:key="modelIndex"
|
|
:value="model.value"
|
|
:selected="claimModel[enumField.name] === model.value"
|
|
>
|
|
{{ model.label }}
|
|
</option>
|
|
</select>
|
|
<button
|
|
v-if="checkIsManualResponseType(enumField.name) && !isTreatedClaim"
|
|
type="button"
|
|
class="btn btn-primary ms-1"
|
|
data-bs-toggle="modal"
|
|
data-bs-target="#manualResponseModal"
|
|
data-bs-tooltip="tooltip"
|
|
:title="trans.methods.__('Répondre au client')"
|
|
>
|
|
<FontAwesomeIcon icon="fa-solid fa-comment-dots" />
|
|
</button>
|
|
</div>
|
|
<small class="text-danger m-0">
|
|
{{ errors.methods.parseValidationInput(`${enumField.name}`, allErrors) }}
|
|
</small>
|
|
</td>
|
|
<template v-else>
|
|
<td
|
|
class="align-middle fw-bold"
|
|
:class="{'border-0': enumFieldIndex === Object.keys(enumFields).length - 1}"
|
|
>
|
|
{{ ucfirst(trans.methods.__(`validation.custom.${enumField.name}`)) }}
|
|
</td>
|
|
<td
|
|
class="align-middle"
|
|
:class="{'border-0': enumFieldIndex === Object.keys(enumFields).length - 1}"
|
|
>
|
|
{{ Object.values(enumField.associatedEnum).find(item => item.value == selectParameters.enums[enumField.name])?.label }}
|
|
</td>
|
|
</template>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
<ClaimManualResponse
|
|
v-if="!isTreatedClaim"
|
|
:claim-model="claimModel"
|
|
:is-manual-response-type="isManualResponseType"
|
|
:claim-template-models="claimTemplateModels"
|
|
@answer-sent="updateMessages"
|
|
/>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { computed, useAttrs, onMounted, ref, reactive } from "vue";
|
|
import type { PropType } from "vue";
|
|
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
|
|
import errors from "./../../modules/errors";
|
|
import trans from "./../../modules/trans";
|
|
import route from "./../../modules/route";
|
|
import { Tooltips } from "./../../modules/tooltips";
|
|
import SearchBelongsToDropdown from "./SearchBelongsToDropdownComponent.vue";
|
|
import ClaimManualResponse from "./ClaimManualResponseComponent.vue";
|
|
|
|
defineOptions({
|
|
name: "ClaimActionsComponent",
|
|
});
|
|
|
|
// * ATTRIBUTES
|
|
const attrs = useAttrs();
|
|
|
|
// * EMITS
|
|
const emits = defineEmits<{
|
|
(e: "updateMessages", value: Array<LaravelModel & LaravelModelUserRelation>): void;
|
|
}>();
|
|
|
|
// * PROPS
|
|
const props = defineProps({
|
|
authUserId: {
|
|
type: Number,
|
|
default: Math.pow(10, 16) / Math.random(),
|
|
},
|
|
claimModel: {
|
|
type: Object as PropType<LaravelModel & LaravelModelClaimRelations>,
|
|
default: () => { return []; },
|
|
},
|
|
brandModels: {
|
|
type: Object as PropType<LaravelPaginator>,
|
|
default: () => { return {}; },
|
|
},
|
|
claimSubjectModels: {
|
|
type: Object as PropType<LaravelPaginator>,
|
|
default: () => { return {}; },
|
|
},
|
|
claimTemplateModels: {
|
|
type: Object as PropType<LaravelPaginator>,
|
|
default: () => { return {}; },
|
|
},
|
|
enums: {
|
|
type: Object as PropType<Record<string, Array<Enum>>>,
|
|
default: () => { return {}; },
|
|
},
|
|
can: {
|
|
type: Object as PropType<Record<string, boolean>>,
|
|
default: () => { return {}; },
|
|
},
|
|
loading: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
isManualResponseType: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
allErrors: {
|
|
type: Object as PropType<LaravelValidationErrors>,
|
|
default: () => { return {}; },
|
|
},
|
|
});
|
|
|
|
// * REFS
|
|
const claimActions = ref<HTMLDivElement|null>(null);
|
|
|
|
// * DATA
|
|
const authUserId = ref<number>(props.authUserId);
|
|
const claimModel = ref<LaravelModel & LaravelModelClaimRelations>(props.claimModel);
|
|
const brandModels = ref<LaravelPaginator>(props.brandModels);
|
|
const claimSubjectModels = ref<LaravelPaginator>(props.claimSubjectModels);
|
|
const claimTemplateModels = ref<LaravelPaginator>(props.claimTemplateModels);
|
|
const loading = ref<boolean>(props.loading);
|
|
const isManualResponseType = ref<boolean>(props.isManualResponseType);
|
|
const tooltips = ref<Tooltips|null>(null);
|
|
const enumFields = ref<Record<number, {
|
|
can: boolean,
|
|
name: string,
|
|
associatedEnum: Array<Enum>,
|
|
}>>({});
|
|
const allErrors = ref<LaravelValidationErrors>(props.allErrors);
|
|
const localVersion = ref<number>(1);
|
|
|
|
/** Enum parameters. */
|
|
const enumParameters = reactive<{
|
|
claimType: Array<Enum>,
|
|
claimStatus: Array<Enum>,
|
|
claimResponseType: Array<Enum>,
|
|
}>({
|
|
claimType: props.enums.claimType,
|
|
claimStatus: props.enums.claimStatus,
|
|
claimResponseType: props.enums.claimResponseType,
|
|
});
|
|
|
|
/** Can parameters. */
|
|
const canParameters = reactive<{
|
|
updateBrand: boolean,
|
|
updateSubject: boolean,
|
|
updateType: boolean,
|
|
updateStatus: boolean,
|
|
updateResponseType: boolean,
|
|
}>({
|
|
updateBrand: props.can.updateBrand,
|
|
updateSubject: props.can.updateSubject,
|
|
updateType: props.can.updateType,
|
|
updateStatus: props.can.updateStatus,
|
|
updateResponseType: props.can.updateResponseType,
|
|
});
|
|
|
|
/** Select parameters. */
|
|
const selectParameters = reactive<{
|
|
brand: LaravelModel,
|
|
subject: LaravelModel|null,
|
|
enums: Record<string,string>,
|
|
}>({
|
|
brand: props.claimModel.brand,
|
|
subject: props.claimModel.claim_subject,
|
|
enums: {
|
|
type: String(props.claimModel.type),
|
|
status: String(props.claimModel.status),
|
|
response_type: String(props.claimModel.response_type),
|
|
},
|
|
});
|
|
|
|
// * COMPUTED
|
|
const isUsedWithProps = computed<boolean>(() => attrs.json === undefined);
|
|
const brandLabel = computed(() => trans.methods.__("models.classes.brands").toString().toLowerCase().replace(/s$/, ""));
|
|
const claimsubjectLabel = computed(() => trans.methods.__("models.classes.claimsubjects").toLowerCase().toString().replace(/s$/, ""));
|
|
const isTreatedClaim = computed(() => Object.values(enumParameters.claimStatus).find(e => e.name === "treated")?.value == selectParameters.enums["status"]);
|
|
|
|
// * LIFECYCLE
|
|
onMounted((): void => {
|
|
const json = String(attrs.json ?? "{}"),
|
|
data = JSON.parse(json);
|
|
if (!isUsedWithProps.value) {
|
|
authUserId.value = data.authUserId;
|
|
claimModel.value = data.claimModel;
|
|
claimSubjectModels.value = data.claimSubjectModels;
|
|
claimTemplateModels.value = data.claimTemplateModels;
|
|
brandModels.value = data.brandModels;
|
|
allErrors.value = data.allErrors;
|
|
|
|
/** Enum parameters. */
|
|
enumParameters.claimType = data.enums.claimType;
|
|
enumParameters.claimStatus = data.enums.claimStatus;
|
|
enumParameters.claimResponseType = data.enums.claimResponseType;
|
|
|
|
/** Can parameters. */
|
|
canParameters.updateBrand = data.can.updateBrand;
|
|
canParameters.updateSubject = data.can.updateSubject;
|
|
canParameters.updateType = data.can.updateType;
|
|
canParameters.updateStatus = data.can.updateStatus;
|
|
canParameters.updateResponseType = data.can.updateResponseType;
|
|
|
|
/** Select parameters. */
|
|
selectParameters.brand = claimModel.value.brand;
|
|
selectParameters.subject = claimModel.value.claim_subject;
|
|
selectParameters.enums.type = String(claimModel.value.type);
|
|
selectParameters.enums.status = String(claimModel.value.status);
|
|
selectParameters.enums.response_type = String(claimModel.value.response_type);
|
|
}
|
|
/** Set enum fields. */
|
|
enumFields.value = [
|
|
{
|
|
can: canParameters.updateType,
|
|
name: "type",
|
|
associatedEnum: enumParameters.claimType,
|
|
},
|
|
{
|
|
can: canParameters.updateStatus,
|
|
name: "status",
|
|
associatedEnum: enumParameters.claimStatus,
|
|
},
|
|
{
|
|
can: canParameters.updateResponseType,
|
|
name: "response_type",
|
|
associatedEnum: enumParameters.claimResponseType,
|
|
},
|
|
];
|
|
initTooltips();
|
|
});
|
|
|
|
/**
|
|
* Set the selected brand.
|
|
* @return void
|
|
*/
|
|
function setSelectedBrand(brandModel: VselectOption|VselectOption[]|null): void {
|
|
selectParameters.brand = brandModel as LaravelModel;
|
|
selectParameters.subject = null;
|
|
fetchClaimSubjects();
|
|
}
|
|
|
|
/**
|
|
* Set the selected subject.
|
|
* @return void
|
|
*/
|
|
function setSelectedSubject(subjectModel: VselectOption|VselectOption[]|null): void {
|
|
selectParameters.subject = subjectModel as LaravelModel;
|
|
delete allErrors.value.subject_id;
|
|
updateClaimData();
|
|
}
|
|
|
|
/**
|
|
* Set the selected subject.
|
|
* @return void
|
|
*/
|
|
function setSelectedEnum(event: Event, field: string): void {
|
|
const selectEnum = event.target as HTMLSelectElement|null;
|
|
selectParameters.enums[field] = selectEnum?.value ?? "";
|
|
delete allErrors.value[field];
|
|
if (checkIsManualResponseType(field)) {
|
|
isManualResponseType.value = true;
|
|
} else {
|
|
updateClaimData();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Fetch all claim subjects from specific brand.
|
|
* @return void
|
|
*/
|
|
function fetchClaimSubjects(): void {
|
|
loading.value = true;
|
|
window.axios
|
|
.get(getClaimSubjectPaginateRoute())
|
|
.then((reponse) => {
|
|
claimSubjectModels.value = reponse.data;
|
|
})
|
|
.catch((e) => {
|
|
loading.value = false;
|
|
allErrors.value = e.response?.data?.errors ?? {};
|
|
errors.methods.ajaxErrorHandler(e);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Fetch all claim subjects from specific brand.
|
|
* @return void
|
|
*/
|
|
function updateClaimData(): void {
|
|
loading.value = true;
|
|
window.axios
|
|
.patch(route.methods.getRoute("bo.claims.update", {
|
|
CLAIMID: String(claimModel.value.id),
|
|
}), {
|
|
brand_id: selectParameters.brand.id,
|
|
subject_id: selectParameters.subject?.id,
|
|
type: selectParameters.enums["type"],
|
|
status: selectParameters.enums["status"],
|
|
response_type: selectParameters.enums["response_type"],
|
|
})
|
|
.then((reponse) => {
|
|
loading.value = false;
|
|
emits("updateMessages", reponse.data);
|
|
})
|
|
.catch((e) => {
|
|
loading.value = false;
|
|
allErrors.value = e.response?.data?.errors ?? {};
|
|
errors.methods.ajaxErrorHandler(e);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Return the claim subject route.
|
|
* @return string
|
|
*/
|
|
function getClaimSubjectPaginateRoute(): string {
|
|
const targetRoute = "bo.claim_subjects.json-paginate";
|
|
const fetchMessageRoute = route.methods.route(targetRoute, {
|
|
BRANDID: String(selectParameters.brand.id),
|
|
});
|
|
if (!fetchMessageRoute) {
|
|
throw new Error(`Undefined ${targetRoute}`);
|
|
}
|
|
return fetchMessageRoute + "?targetModel=App\\Models\\ClaimSubject&page=1&paginate=5&fieldName=label";
|
|
}
|
|
|
|
/**
|
|
* Check if it's manual response when the response_type select changed.
|
|
* @param boolean fieldName
|
|
* @return string
|
|
*/
|
|
function checkIsManualResponseType(fieldName: string): boolean {
|
|
return selectParameters.enums["response_type"] === "2" && fieldName === "response_type";
|
|
}
|
|
|
|
/**
|
|
* Event propagation to update all messages in the conversation.
|
|
* @param Array value
|
|
* @return void
|
|
*/
|
|
function updateMessages(value: Array<LaravelModel & LaravelModelUserRelation>): void {
|
|
selectParameters.enums["status"] = "4";
|
|
localVersion.value = localVersion.value + 1;
|
|
emits("updateMessages", value);
|
|
}
|
|
|
|
/**
|
|
* Initialise all tooltips in the component.
|
|
* @return void
|
|
*/
|
|
function initTooltips(): void {
|
|
setTimeout(() => {
|
|
tooltips.value = Tooltips.make({
|
|
type: "dom",
|
|
elements: claimActions.value!.querySelectorAll("[data-bs-tooltip=\"tooltip\"]")
|
|
});
|
|
}, 500);
|
|
}
|
|
|
|
/**
|
|
*Capitalize the first letter.
|
|
* @return string
|
|
*/
|
|
function ucfirst(str: string): string {
|
|
if (!str) return "";
|
|
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
}
|
|
</script>
|