iachat/app/javascript/dashboard/routes/dashboard/settings/sla/SlaForm.vue
2025-07-01 09:43:44 +05:30

227 lines
6.4 KiB
Vue

<script>
import { mapGetters } from 'vuex';
import { convertSecondsToTimeUnit } from '@chatwoot/utils';
import validations from './validations';
import SlaTimeInput from './SlaTimeInput.vue';
import NextButton from 'dashboard/components-next/button/Button.vue';
import { useVuelidate } from '@vuelidate/core';
export default {
components: {
SlaTimeInput,
NextButton,
},
props: {
selectedResponse: {
type: Object,
default: () => {},
},
submitLabel: {
type: String,
required: true,
},
},
emits: ['close', 'submitSla'],
setup() {
return { v$: useVuelidate() };
},
data() {
return {
name: '',
description: '',
isSlaTimeInputsInvalid: false,
slaTimeInputsValidation: {},
slaTimeInputs: [
{
threshold: null,
unit: 'Minutes',
label: 'SLA.FORM.FIRST_RESPONSE_TIME.LABEL',
placeholder: 'SLA.FORM.FIRST_RESPONSE_TIME.PLACEHOLDER',
},
{
threshold: null,
unit: 'Minutes',
label: 'SLA.FORM.NEXT_RESPONSE_TIME.LABEL',
placeholder: 'SLA.FORM.NEXT_RESPONSE_TIME.PLACEHOLDER',
},
{
threshold: null,
unit: 'Minutes',
label: 'SLA.FORM.RESOLUTION_TIME.LABEL',
placeholder: 'SLA.FORM.RESOLUTION_TIME.PLACEHOLDER',
},
],
onlyDuringBusinessHours: false,
};
},
validations,
computed: {
...mapGetters({
uiFlags: 'sla/getUIFlags',
}),
isSubmitDisabled() {
return (
this.v$.name.$invalid ||
this.isSlaTimeInputsInvalid ||
this.uiFlags.isUpdating
);
},
slaNameErrorMessage() {
let errorMessage = '';
if (this.v$.name.$error) {
if (!this.v$.name.required) {
errorMessage = this.$t('SLA.FORM.NAME.REQUIRED_ERROR');
} else if (!this.v$.name.minLength) {
errorMessage = this.$t('SLA.FORM.NAME.MINIMUM_LENGTH_ERROR');
}
}
return errorMessage;
},
},
mounted() {
if (this.selectedResponse) this.setFormValues();
},
methods: {
onClose() {
this.$emit('close');
},
setFormValues() {
const {
name,
description,
first_response_time_threshold: firstResponseTimeThreshold,
next_response_time_threshold: nextResponseTimeThreshold,
resolution_time_threshold: resolutionTimeThreshold,
only_during_business_hours: onlyDuringBusinessHours,
} = this.selectedResponse;
this.name = name;
this.description = description;
this.onlyDuringBusinessHours = onlyDuringBusinessHours;
const thresholds = [
firstResponseTimeThreshold,
nextResponseTimeThreshold,
resolutionTimeThreshold,
];
this.slaTimeInputs.forEach((input, index) => {
const converted = convertSecondsToTimeUnit(thresholds[index], {
minute: 'Minutes',
hour: 'Hours',
day: 'Days',
});
input.threshold = converted.time;
input.unit = converted.unit;
});
},
updateThreshold(index, value) {
this.slaTimeInputs[index].threshold = value;
},
updateUnit(index, unit) {
this.slaTimeInputs[index].unit = unit;
},
onSubmit() {
const payload = {
name: this.name,
description: this.description,
first_response_time_threshold: this.convertToSeconds(0),
next_response_time_threshold: this.convertToSeconds(1),
resolution_time_threshold: this.convertToSeconds(2),
only_during_business_hours: this.onlyDuringBusinessHours,
};
this.$emit('submitSla', payload);
},
convertToSeconds(index) {
const { threshold, unit } = this.slaTimeInputs[index];
if (threshold === null || threshold === 0) return null;
const unitsToSeconds = { Minutes: 60, Hours: 3600, Days: 86400 };
return Number(threshold * (unitsToSeconds[unit] || 1));
},
handleIsInvalid(index, isInvalid) {
this.slaTimeInputsValidation = {
...this.slaTimeInputsValidation,
[index]: isInvalid,
};
this.checkValidationState();
},
checkValidationState() {
const isAnyInvalid = Object.values(this.slaTimeInputsValidation).some(
isInvalid => isInvalid
);
this.isSlaTimeInputsInvalid = isAnyInvalid;
},
},
};
</script>
<template>
<div class="flex flex-col h-auto overflow-auto">
<form class="flex flex-wrap mx-0" @submit.prevent="onSubmit">
<woot-input
v-model="name"
:class="{ error: v$.name.$error }"
class="w-full"
:styles="{
borderRadius: '0.75rem',
padding: '0.375rem 0.75rem',
fontSize: '0.875rem',
}"
:label="$t('SLA.FORM.NAME.LABEL')"
:placeholder="$t('SLA.FORM.NAME.PLACEHOLDER')"
:error="slaNameErrorMessage"
@input="v$.name.$touch"
@blur="v$.name.$touch"
/>
<woot-input
v-model="description"
class="w-full"
:styles="{
borderRadius: '0.75rem',
padding: '0.375rem 0.75rem',
fontSize: '0.875rem',
}"
:label="$t('SLA.FORM.DESCRIPTION.LABEL')"
:placeholder="$t('SLA.FORM.DESCRIPTION.PLACEHOLDER')"
/>
<SlaTimeInput
v-for="(input, index) in slaTimeInputs"
:key="index"
:threshold="input.threshold"
:threshold-unit="input.unit"
:label="$t(input.label)"
:placeholder="$t(input.placeholder)"
@update-threshold="updateThreshold(index, $event)"
@unit="updateUnit(index, $event)"
@is-in-valid="handleIsInvalid(index, $event)"
/>
<div
class="mt-3 flex h-10 items-center text-sm w-full gap-2 border border-solid border-n-strong px-3 py-1.5 rounded-xl justify-between"
>
<span for="sla_bh" class="text-n-slate-11">
{{ $t('SLA.FORM.BUSINESS_HOURS.PLACEHOLDER') }}
</span>
<woot-switch id="sla_bh" v-model="onlyDuringBusinessHours" />
</div>
<div class="flex items-center justify-end w-full gap-2 mt-8">
<NextButton
faded
slate
type="reset"
:label="$t('SLA.FORM.CANCEL')"
@click.prevent="onClose"
/>
<NextButton
type="submit"
:label="submitLabel"
:disabled="isSubmitDisabled"
:is-loading="uiFlags.isUpdating"
/>
</div>
</form>
</div>
</template>