feat: Agent assignment policy Create/Edit pages (#12400)
This commit is contained in:
@@ -3,6 +3,8 @@ import { frontendURL } from '../../../../helper/URLHelper';
|
||||
import SettingsWrapper from '../SettingsWrapper.vue';
|
||||
import AssignmentPolicyIndex from './Index.vue';
|
||||
import AgentAssignmentIndex from './pages/AgentAssignmentIndexPage.vue';
|
||||
import AgentAssignmentCreate from './pages/AgentAssignmentCreatePage.vue';
|
||||
import AgentAssignmentEdit from './pages/AgentAssignmentEditPage.vue';
|
||||
|
||||
export default {
|
||||
routes: [
|
||||
@@ -34,6 +36,24 @@ export default {
|
||||
permissions: ['administrator'],
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'assignment/create',
|
||||
name: 'agent_assignment_policy_create',
|
||||
component: AgentAssignmentCreate,
|
||||
meta: {
|
||||
featureFlag: FEATURE_FLAGS.ASSIGNMENT_V2,
|
||||
permissions: ['administrator'],
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'assignment/edit/:id',
|
||||
name: 'agent_assignment_policy_edit',
|
||||
component: AgentAssignmentEdit,
|
||||
meta: {
|
||||
featureFlag: FEATURE_FLAGS.ASSIGNMENT_V2,
|
||||
permissions: ['administrator'],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
// Assignment order types
|
||||
export const ROUND_ROBIN = 'round_robin';
|
||||
export const BALANCED = 'balanced';
|
||||
|
||||
// Assignment priority types
|
||||
export const EARLIEST_CREATED = 'earliest_created';
|
||||
export const LONGEST_WAITING = 'longest_waiting';
|
||||
|
||||
// Default values for fair distribution
|
||||
export const DEFAULT_FAIR_DISTRIBUTION_LIMIT = 100;
|
||||
export const DEFAULT_FAIR_DISTRIBUTION_WINDOW = 3600;
|
||||
|
||||
// Options groupings
|
||||
export const OPTIONS = {
|
||||
ORDER: [ROUND_ROBIN, BALANCED],
|
||||
PRIORITY: [EARLIEST_CREATED, LONGEST_WAITING],
|
||||
};
|
||||
@@ -0,0 +1,74 @@
|
||||
<script setup>
|
||||
import { computed, ref } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useStore, useMapGetter } from 'dashboard/composables/store';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { useAlert } from 'dashboard/composables';
|
||||
|
||||
import Breadcrumb from 'dashboard/components-next/breadcrumb/Breadcrumb.vue';
|
||||
import SettingsLayout from 'dashboard/routes/dashboard/settings/SettingsLayout.vue';
|
||||
import AssignmentPolicyForm from 'dashboard/routes/dashboard/settings/assignmentPolicy/pages/components/AgentAssignmentPolicyForm.vue';
|
||||
|
||||
const router = useRouter();
|
||||
const store = useStore();
|
||||
const { t } = useI18n();
|
||||
|
||||
const formRef = ref(null);
|
||||
const uiFlags = useMapGetter('assignmentPolicies/getUIFlags');
|
||||
|
||||
const breadcrumbItems = computed(() => [
|
||||
{
|
||||
label: t('ASSIGNMENT_POLICY.AGENT_ASSIGNMENT_POLICY.INDEX.HEADER.TITLE'),
|
||||
routeName: 'agent_assignment_policy_index',
|
||||
},
|
||||
{
|
||||
label: t('ASSIGNMENT_POLICY.AGENT_ASSIGNMENT_POLICY.CREATE.HEADER.TITLE'),
|
||||
},
|
||||
]);
|
||||
|
||||
const handleBreadcrumbClick = item => {
|
||||
router.push({
|
||||
name: item.routeName,
|
||||
});
|
||||
};
|
||||
|
||||
const handleSubmit = async formState => {
|
||||
try {
|
||||
const policy = await store.dispatch('assignmentPolicies/create', formState);
|
||||
useAlert(
|
||||
t('ASSIGNMENT_POLICY.AGENT_ASSIGNMENT_POLICY.CREATE.API.SUCCESS_MESSAGE')
|
||||
);
|
||||
formRef.value?.resetForm();
|
||||
|
||||
router.push({
|
||||
name: 'agent_assignment_policy_edit',
|
||||
params: {
|
||||
id: policy.id,
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
useAlert(
|
||||
t('ASSIGNMENT_POLICY.AGENT_ASSIGNMENT_POLICY.CREATE.API.ERROR_MESSAGE')
|
||||
);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<SettingsLayout class="xl:px-44">
|
||||
<template #header>
|
||||
<div class="flex items-center gap-2 w-full justify-between">
|
||||
<Breadcrumb :items="breadcrumbItems" @click="handleBreadcrumbClick" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #body>
|
||||
<AssignmentPolicyForm
|
||||
ref="formRef"
|
||||
mode="CREATE"
|
||||
:is-loading="uiFlags.isCreating"
|
||||
@submit="handleSubmit"
|
||||
/>
|
||||
</template>
|
||||
</SettingsLayout>
|
||||
</template>
|
||||
@@ -0,0 +1,197 @@
|
||||
<script setup>
|
||||
import { computed, ref, watch } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useStore, useMapGetter } from 'dashboard/composables/store';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import { useAlert } from 'dashboard/composables';
|
||||
import { getInboxIconByType } from 'dashboard/helper/inbox';
|
||||
import {
|
||||
ROUND_ROBIN,
|
||||
EARLIEST_CREATED,
|
||||
} from 'dashboard/routes/dashboard/settings/assignmentPolicy/constants';
|
||||
|
||||
import Breadcrumb from 'dashboard/components-next/breadcrumb/Breadcrumb.vue';
|
||||
import SettingsLayout from 'dashboard/routes/dashboard/settings/SettingsLayout.vue';
|
||||
import AssignmentPolicyForm from 'dashboard/routes/dashboard/settings/assignmentPolicy/pages/components/AgentAssignmentPolicyForm.vue';
|
||||
import ConfirmInboxDialog from 'dashboard/routes/dashboard/settings/assignmentPolicy/pages/components/ConfirmInboxDialog.vue';
|
||||
|
||||
const BASE_KEY = 'ASSIGNMENT_POLICY.AGENT_ASSIGNMENT_POLICY';
|
||||
|
||||
const { t } = useI18n();
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const store = useStore();
|
||||
|
||||
const uiFlags = useMapGetter('assignmentPolicies/getUIFlags');
|
||||
const inboxes = useMapGetter('inboxes/getAllInboxes');
|
||||
const inboxUiFlags = useMapGetter('assignmentPolicies/getInboxUiFlags');
|
||||
const selectedPolicyById = useMapGetter(
|
||||
'assignmentPolicies/getAssignmentPolicyById'
|
||||
);
|
||||
|
||||
const routeId = computed(() => route.params.id);
|
||||
const selectedPolicy = computed(() => selectedPolicyById.value(routeId.value));
|
||||
|
||||
const confirmInboxDialogRef = ref(null);
|
||||
// Store the policy linked to the inbox when adding a new inbox
|
||||
const inboxLinkedPolicy = ref(null);
|
||||
|
||||
const breadcrumbItems = computed(() => [
|
||||
{
|
||||
label: t(`${BASE_KEY}.INDEX.HEADER.TITLE`),
|
||||
routeName: 'agent_assignment_policy_index',
|
||||
},
|
||||
{ label: t(`${BASE_KEY}.EDIT.HEADER.TITLE`) },
|
||||
]);
|
||||
|
||||
const buildInboxList = allInboxes =>
|
||||
allInboxes?.map(({ name, id, email, phoneNumber, channelType, medium }) => ({
|
||||
name,
|
||||
id,
|
||||
email,
|
||||
phoneNumber,
|
||||
icon: getInboxIconByType(channelType, medium, 'line'),
|
||||
})) || [];
|
||||
|
||||
const policyInboxes = computed(() =>
|
||||
buildInboxList(selectedPolicy.value?.inboxes)
|
||||
);
|
||||
|
||||
const inboxList = computed(() =>
|
||||
buildInboxList(
|
||||
inboxes.value?.slice().sort((a, b) => a.name.localeCompare(b.name))
|
||||
)
|
||||
);
|
||||
|
||||
const formData = computed(() => ({
|
||||
name: selectedPolicy.value?.name || '',
|
||||
description: selectedPolicy.value?.description || '',
|
||||
enabled: selectedPolicy.value?.enabled || false,
|
||||
assignmentOrder: selectedPolicy.value?.assignmentOrder || ROUND_ROBIN,
|
||||
conversationPriority:
|
||||
selectedPolicy.value?.conversationPriority || EARLIEST_CREATED,
|
||||
fairDistributionLimit: selectedPolicy.value?.fairDistributionLimit || 10,
|
||||
fairDistributionWindow: selectedPolicy.value?.fairDistributionWindow || 60,
|
||||
}));
|
||||
|
||||
const handleDeleteInbox = inboxId =>
|
||||
store.dispatch('assignmentPolicies/removeInboxPolicy', {
|
||||
policyId: selectedPolicy.value?.id,
|
||||
inboxId,
|
||||
});
|
||||
|
||||
const handleBreadcrumbClick = ({ routeName }) =>
|
||||
router.push({ name: routeName });
|
||||
|
||||
const setInboxPolicy = async (inboxId, policyId) => {
|
||||
try {
|
||||
await store.dispatch('assignmentPolicies/setInboxPolicy', {
|
||||
inboxId,
|
||||
policyId,
|
||||
});
|
||||
useAlert(t(`${BASE_KEY}.FORM.INBOXES.API.SUCCESS_MESSAGE`));
|
||||
await store.dispatch(
|
||||
'assignmentPolicies/getInboxes',
|
||||
Number(routeId.value)
|
||||
);
|
||||
return true;
|
||||
} catch (error) {
|
||||
useAlert(t(`${BASE_KEY}.FORM.INBOXES.API.ERROR_MESSAGE`));
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
const handleAddInbox = async inbox => {
|
||||
try {
|
||||
const policy = await store.dispatch('assignmentPolicies/getInboxPolicy', {
|
||||
inboxId: inbox?.id,
|
||||
});
|
||||
|
||||
if (policy?.id !== selectedPolicy.value?.id) {
|
||||
inboxLinkedPolicy.value = {
|
||||
...policy,
|
||||
assignedInboxCount: policy.assignedInboxCount - 1,
|
||||
};
|
||||
confirmInboxDialogRef.value.openDialog(inbox);
|
||||
return;
|
||||
}
|
||||
} catch (error) {
|
||||
// If getInboxPolicy fails, continue to setInboxPolicy
|
||||
}
|
||||
|
||||
await setInboxPolicy(inbox?.id, selectedPolicy.value?.id);
|
||||
};
|
||||
|
||||
const handleConfirmAddInbox = async inboxId => {
|
||||
const success = await setInboxPolicy(inboxId, selectedPolicy.value?.id);
|
||||
|
||||
if (success) {
|
||||
// Update the policy to reflect the assigned inbox count change
|
||||
await store.dispatch('assignmentPolicies/updateInboxPolicy', {
|
||||
policy: inboxLinkedPolicy.value,
|
||||
});
|
||||
// Fetch the updated inboxes for the policy after update, to reflect real-time changes
|
||||
store.dispatch(
|
||||
'assignmentPolicies/getInboxes',
|
||||
inboxLinkedPolicy.value?.id
|
||||
);
|
||||
inboxLinkedPolicy.value = null;
|
||||
confirmInboxDialogRef.value.closeDialog();
|
||||
}
|
||||
};
|
||||
|
||||
const handleSubmit = async formState => {
|
||||
try {
|
||||
await store.dispatch('assignmentPolicies/update', {
|
||||
id: selectedPolicy.value?.id,
|
||||
...formState,
|
||||
});
|
||||
useAlert(t(`${BASE_KEY}.EDIT.API.SUCCESS_MESSAGE`));
|
||||
} catch {
|
||||
useAlert(t(`${BASE_KEY}.EDIT.API.ERROR_MESSAGE`));
|
||||
}
|
||||
};
|
||||
|
||||
const fetchPolicyData = async () => {
|
||||
if (!routeId.value) return;
|
||||
|
||||
// Fetch policy if not available
|
||||
if (!selectedPolicy.value?.id)
|
||||
await store.dispatch('assignmentPolicies/show', routeId.value);
|
||||
|
||||
await store.dispatch('assignmentPolicies/getInboxes', Number(routeId.value));
|
||||
};
|
||||
|
||||
watch(routeId, fetchPolicyData, { immediate: true });
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<SettingsLayout :is-loading="uiFlags.isFetchingItem" class="xl:px-44">
|
||||
<template #header>
|
||||
<div class="flex items-center gap-2 w-full justify-between">
|
||||
<Breadcrumb :items="breadcrumbItems" @click="handleBreadcrumbClick" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #body>
|
||||
<AssignmentPolicyForm
|
||||
:key="routeId"
|
||||
mode="EDIT"
|
||||
:initial-data="formData"
|
||||
:policy-inboxes="policyInboxes"
|
||||
:inbox-list="inboxList"
|
||||
show-inbox-section
|
||||
:is-loading="uiFlags.isUpdating"
|
||||
:is-inbox-loading="inboxUiFlags.isFetching"
|
||||
@submit="handleSubmit"
|
||||
@add-inbox="handleAddInbox"
|
||||
@delete-inbox="handleDeleteInbox"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<ConfirmInboxDialog
|
||||
ref="confirmInboxDialogRef"
|
||||
@add="handleConfirmAddInbox"
|
||||
/>
|
||||
</SettingsLayout>
|
||||
</template>
|
||||
@@ -44,7 +44,16 @@ const handleBreadcrumbClick = item => {
|
||||
|
||||
const onClickCreatePolicy = () => {
|
||||
router.push({
|
||||
name: 'assignment_policy_create',
|
||||
name: 'agent_assignment_policy_create',
|
||||
});
|
||||
};
|
||||
|
||||
const onClickEditPolicy = id => {
|
||||
router.push({
|
||||
name: 'agent_assignment_policy_edit',
|
||||
params: {
|
||||
id,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
@@ -106,6 +115,7 @@ onMounted(() => {
|
||||
v-bind="policy"
|
||||
:is-fetching-inboxes="inboxUiFlags.isFetching"
|
||||
@fetch-inboxes="handleFetchInboxes"
|
||||
@edit="onClickEditPolicy"
|
||||
@delete="handleDelete"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,254 @@
|
||||
<script setup>
|
||||
import { computed, reactive, ref, watch } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useConfig } from 'dashboard/composables/useConfig';
|
||||
import BaseInfo from 'dashboard/components-next/AssignmentPolicy/components/BaseInfo.vue';
|
||||
import RadioCard from 'dashboard/components-next/AssignmentPolicy/components/RadioCard.vue';
|
||||
import FairDistribution from 'dashboard/components-next/AssignmentPolicy/components/FairDistribution.vue';
|
||||
import DataTable from 'dashboard/components-next/AssignmentPolicy/components/DataTable.vue';
|
||||
import AddDataDropdown from 'dashboard/components-next/AssignmentPolicy/components/AddDataDropdown.vue';
|
||||
import WithLabel from 'v3/components/Form/WithLabel.vue';
|
||||
import Button from 'dashboard/components-next/button/Button.vue';
|
||||
import {
|
||||
OPTIONS,
|
||||
ROUND_ROBIN,
|
||||
EARLIEST_CREATED,
|
||||
DEFAULT_FAIR_DISTRIBUTION_LIMIT,
|
||||
DEFAULT_FAIR_DISTRIBUTION_WINDOW,
|
||||
} from 'dashboard/routes/dashboard/settings/assignmentPolicy/constants';
|
||||
|
||||
const props = defineProps({
|
||||
initialData: {
|
||||
type: Object,
|
||||
default: () => ({
|
||||
name: '',
|
||||
description: '',
|
||||
enabled: false,
|
||||
assignmentOrder: ROUND_ROBIN,
|
||||
conversationPriority: EARLIEST_CREATED,
|
||||
fairDistributionLimit: DEFAULT_FAIR_DISTRIBUTION_LIMIT,
|
||||
fairDistributionWindow: DEFAULT_FAIR_DISTRIBUTION_WINDOW,
|
||||
}),
|
||||
},
|
||||
mode: {
|
||||
type: String,
|
||||
required: true,
|
||||
validator: value => ['CREATE', 'EDIT'].includes(value),
|
||||
},
|
||||
policyInboxes: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
inboxList: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
showInboxSection: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
isLoading: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
isInboxLoading: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits([
|
||||
'submit',
|
||||
'addInbox',
|
||||
'deleteInbox',
|
||||
'validationChange',
|
||||
]);
|
||||
|
||||
const { t } = useI18n();
|
||||
const { isEnterprise } = useConfig();
|
||||
|
||||
const BASE_KEY = 'ASSIGNMENT_POLICY.AGENT_ASSIGNMENT_POLICY';
|
||||
|
||||
const state = reactive({
|
||||
name: '',
|
||||
description: '',
|
||||
enabled: false,
|
||||
assignmentOrder: ROUND_ROBIN,
|
||||
conversationPriority: EARLIEST_CREATED,
|
||||
fairDistributionLimit: DEFAULT_FAIR_DISTRIBUTION_LIMIT,
|
||||
fairDistributionWindow: DEFAULT_FAIR_DISTRIBUTION_WINDOW,
|
||||
});
|
||||
|
||||
const validationState = ref({
|
||||
isValid: false,
|
||||
});
|
||||
|
||||
const createOption = (type, key, stateKey) => ({
|
||||
key,
|
||||
label: t(`${BASE_KEY}.FORM.${type}.${key.toUpperCase()}.LABEL`),
|
||||
description: t(`${BASE_KEY}.FORM.${type}.${key.toUpperCase()}.DESCRIPTION`),
|
||||
isActive: state[stateKey] === key,
|
||||
});
|
||||
|
||||
const assignmentOrderOptions = computed(() => {
|
||||
const options = OPTIONS.ORDER.filter(
|
||||
key => isEnterprise || key !== 'balanced'
|
||||
);
|
||||
return options.map(key =>
|
||||
createOption('ASSIGNMENT_ORDER', key, 'assignmentOrder')
|
||||
);
|
||||
});
|
||||
|
||||
const assignmentPriorityOptions = computed(() =>
|
||||
OPTIONS.PRIORITY.map(key =>
|
||||
createOption('ASSIGNMENT_PRIORITY', key, 'conversationPriority')
|
||||
)
|
||||
);
|
||||
|
||||
const radioSections = computed(() => [
|
||||
{
|
||||
key: 'assignmentOrder',
|
||||
label: t(`${BASE_KEY}.FORM.ASSIGNMENT_ORDER.LABEL`),
|
||||
options: assignmentOrderOptions.value,
|
||||
},
|
||||
{
|
||||
key: 'conversationPriority',
|
||||
label: t(`${BASE_KEY}.FORM.ASSIGNMENT_PRIORITY.LABEL`),
|
||||
options: assignmentPriorityOptions.value,
|
||||
},
|
||||
]);
|
||||
|
||||
const buttonLabel = computed(() =>
|
||||
t(`${BASE_KEY}.${props.mode.toUpperCase()}.${props.mode}_BUTTON`)
|
||||
);
|
||||
|
||||
const handleValidationChange = validation => {
|
||||
validationState.value = validation;
|
||||
emit('validationChange', validation);
|
||||
};
|
||||
|
||||
const resetForm = () => {
|
||||
Object.assign(state, {
|
||||
name: '',
|
||||
description: '',
|
||||
enabled: false,
|
||||
assignmentOrder: ROUND_ROBIN,
|
||||
conversationPriority: EARLIEST_CREATED,
|
||||
fairDistributionLimit: DEFAULT_FAIR_DISTRIBUTION_LIMIT,
|
||||
fairDistributionWindow: DEFAULT_FAIR_DISTRIBUTION_WINDOW,
|
||||
});
|
||||
};
|
||||
|
||||
const handleSubmit = () => {
|
||||
emit('submit', { ...state });
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.initialData,
|
||||
newData => {
|
||||
Object.assign(state, newData);
|
||||
},
|
||||
{ immediate: true, deep: true }
|
||||
);
|
||||
|
||||
defineExpose({
|
||||
resetForm,
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<form @submit.prevent="handleSubmit">
|
||||
<div class="flex flex-col gap-4 divide-y divide-n-weak mb-4">
|
||||
<BaseInfo
|
||||
v-model:policy-name="state.name"
|
||||
v-model:description="state.description"
|
||||
v-model:enabled="state.enabled"
|
||||
:name-label="t(`${BASE_KEY}.FORM.NAME.LABEL`)"
|
||||
:name-placeholder="t(`${BASE_KEY}.FORM.NAME.PLACEHOLDER`)"
|
||||
:description-label="t(`${BASE_KEY}.FORM.DESCRIPTION.LABEL`)"
|
||||
:description-placeholder="t(`${BASE_KEY}.FORM.DESCRIPTION.PLACEHOLDER`)"
|
||||
:status-label="t(`${BASE_KEY}.FORM.STATUS.LABEL`)"
|
||||
:status-placeholder="
|
||||
t(`${BASE_KEY}.FORM.STATUS.${state.enabled ? 'ACTIVE' : 'INACTIVE'}`)
|
||||
"
|
||||
@validation-change="handleValidationChange"
|
||||
/>
|
||||
|
||||
<div class="flex flex-col items-center">
|
||||
<div
|
||||
v-for="section in radioSections"
|
||||
:key="section.key"
|
||||
class="py-4 flex flex-col items-start gap-3 w-full"
|
||||
>
|
||||
<WithLabel
|
||||
:label="section.label"
|
||||
name="assignmentPolicy"
|
||||
class="w-full flex items-start flex-col gap-3"
|
||||
>
|
||||
<div class="grid grid-cols-1 xs:grid-cols-2 gap-4 w-full">
|
||||
<RadioCard
|
||||
v-for="option in section.options"
|
||||
:id="option.key"
|
||||
:key="option.key"
|
||||
:label="option.label"
|
||||
:description="option.description"
|
||||
:is-active="option.isActive"
|
||||
@select="state[section.key] = $event"
|
||||
/>
|
||||
</div>
|
||||
</WithLabel>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="pt-4 pb-2 flex-col flex gap-4">
|
||||
<div class="flex flex-col items-start gap-1 py-1">
|
||||
<label class="text-sm font-medium text-n-slate-12 py-1">
|
||||
{{ t(`${BASE_KEY}.FORM.FAIR_DISTRIBUTION.LABEL`) }}
|
||||
</label>
|
||||
<p class="mb-0 text-n-slate-11 text-sm">
|
||||
{{ t(`${BASE_KEY}.FORM.FAIR_DISTRIBUTION.DESCRIPTION`) }}
|
||||
</p>
|
||||
</div>
|
||||
<FairDistribution
|
||||
v-model:fair-distribution-limit="state.fairDistributionLimit"
|
||||
v-model:fair-distribution-window="state.fairDistributionWindow"
|
||||
v-model:window-unit="state.windowUnit"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div v-if="showInboxSection" class="py-4 flex-col flex gap-4">
|
||||
<div class="flex items-end gap-4 w-full justify-between">
|
||||
<div class="flex flex-col items-start gap-1 py-1">
|
||||
<label class="text-sm font-medium text-n-slate-12 py-1">
|
||||
{{ t(`${BASE_KEY}.FORM.INBOXES.LABEL`) }}
|
||||
</label>
|
||||
<p class="mb-0 text-n-slate-11 text-sm">
|
||||
{{ t(`${BASE_KEY}.FORM.INBOXES.DESCRIPTION`) }}
|
||||
</p>
|
||||
</div>
|
||||
<AddDataDropdown
|
||||
:label="t(`${BASE_KEY}.FORM.INBOXES.ADD_BUTTON`)"
|
||||
:search-placeholder="
|
||||
t(`${BASE_KEY}.FORM.INBOXES.DROPDOWN.SEARCH_PLACEHOLDER`)
|
||||
"
|
||||
:items="inboxList"
|
||||
@add="$emit('addInbox', $event)"
|
||||
/>
|
||||
</div>
|
||||
<DataTable
|
||||
:items="policyInboxes"
|
||||
:is-fetching="isInboxLoading"
|
||||
:empty-state-message="t(`${BASE_KEY}.FORM.INBOXES.EMPTY_STATE`)"
|
||||
@delete="$emit('deleteInbox', $event)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Button
|
||||
type="submit"
|
||||
:label="buttonLabel"
|
||||
:disabled="!validationState.isValid || isLoading"
|
||||
:is-loading="isLoading"
|
||||
/>
|
||||
</form>
|
||||
</template>
|
||||
@@ -0,0 +1,59 @@
|
||||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
import Dialog from 'dashboard/components-next/dialog/Dialog.vue';
|
||||
|
||||
const emit = defineEmits(['add']);
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const dialogRef = ref(null);
|
||||
const currentInbox = ref(null);
|
||||
|
||||
const openDialog = inbox => {
|
||||
currentInbox.value = inbox;
|
||||
dialogRef.value.open();
|
||||
};
|
||||
|
||||
const closeDialog = () => {
|
||||
dialogRef.value.close();
|
||||
};
|
||||
|
||||
const handleDialogConfirm = () => {
|
||||
emit('add', currentInbox.value.id);
|
||||
};
|
||||
|
||||
defineExpose({ openDialog, closeDialog });
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Dialog
|
||||
ref="dialogRef"
|
||||
type="alert"
|
||||
:title="
|
||||
t(
|
||||
'ASSIGNMENT_POLICY.AGENT_ASSIGNMENT_POLICY.EDIT.CONFIRM_ADD_INBOX_DIALOG.TITLE'
|
||||
)
|
||||
"
|
||||
:description="
|
||||
t(
|
||||
'ASSIGNMENT_POLICY.AGENT_ASSIGNMENT_POLICY.EDIT.CONFIRM_ADD_INBOX_DIALOG.DESCRIPTION',
|
||||
{
|
||||
inboxName: currentInbox?.name,
|
||||
}
|
||||
)
|
||||
"
|
||||
:confirm-button-label="
|
||||
t(
|
||||
'ASSIGNMENT_POLICY.AGENT_ASSIGNMENT_POLICY.EDIT.CONFIRM_ADD_INBOX_DIALOG.CONFIRM_BUTTON_LABEL'
|
||||
)
|
||||
"
|
||||
:cancel-button-label="
|
||||
t(
|
||||
'ASSIGNMENT_POLICY.AGENT_ASSIGNMENT_POLICY.EDIT.CONFIRM_ADD_INBOX_DIALOG.CANCEL_BUTTON_LABEL'
|
||||
)
|
||||
"
|
||||
@confirm="handleDialogConfirm"
|
||||
/>
|
||||
</template>
|
||||
Reference in New Issue
Block a user