This commit is contained in:
Rodrigo Borba 2026-01-13 18:51:18 -03:00
parent 739e042406
commit b50efdd0f9
5 changed files with 46 additions and 12 deletions

View File

@ -1,4 +1,5 @@
<script setup>
/* eslint-disable @intlify/vue-i18n/no-dynamic-keys */
import { ref, computed } from 'vue';
import { useStore } from 'dashboard/composables/store';
import { useAlert } from 'dashboard/composables';
@ -35,6 +36,7 @@ const i18nKey = computed(
() => `CAPTAIN.ASSISTANTS.${props.type.toUpperCase()}`
);
/* eslint-disable @intlify/vue-i18n/no-dynamic-keys */
const createAssistant = async assistantDetails => {
try {
const newAssistant = await store.dispatch(
@ -43,6 +45,7 @@ const createAssistant = async assistantDetails => {
);
emit('created', newAssistant);
} catch (error) {
// eslint-disable-next-line @intlify/vue-i18n/no-dynamic-keys
const errorMessage = error?.message || t(`${i18nKey.value}.ERROR_MESSAGE`);
useAlert(errorMessage);
}
@ -55,13 +58,16 @@ const handleSubmit = async updatedAssistant => {
} else {
await createAssistant(updatedAssistant);
}
// eslint-disable-next-line @intlify/vue-i18n/no-dynamic-keys
useAlert(t(`${i18nKey.value}.SUCCESS_MESSAGE`));
dialogRef.value.close();
} catch (error) {
// eslint-disable-next-line @intlify/vue-i18n/no-dynamic-keys
const errorMessage = error?.message || t(`${i18nKey.value}.ERROR_MESSAGE`);
useAlert(errorMessage);
}
};
/* eslint-enable @intlify/vue-i18n/no-dynamic-keys */
const handleClose = () => {
emit('close');
@ -76,9 +82,10 @@ defineExpose({ dialogRef });
<template>
<!-- eslint-disable vue/no-bare-strings-in-template -->
<!-- eslint-disable @intlify/vue-i18n/no-dynamic-keys -->
<Dialog
ref="dialogRef"
type="edit"
:type="type"
:title="t(`${i18nKey}.TITLE`)"
:description="t('CAPTAIN.ASSISTANTS.FORM_DESCRIPTION')"
:show-cancel-button="false"

View File

@ -1,10 +1,10 @@
<script setup>
import { reactive, computed, onMounted } from 'vue';
import { reactive, computed, onMounted, watch } from 'vue';
import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n';
import { useVuelidate } from '@vuelidate/core';
import { required } from '@vuelidate/validators';
import { useMapGetter } from 'dashboard/composables/store';
import axios from 'axios';
import Button from 'dashboard/components-next/button/Button.vue';
import ComboBox from 'dashboard/components-next/combobox/ComboBox.vue';
@ -19,6 +19,7 @@ const props = defineProps({
const emit = defineEmits(['submit', 'cancel']);
const { t } = useI18n();
const route = useRoute();
const formState = {
uiFlags: useMapGetter('captainInboxes/getUIFlags'),
@ -38,6 +39,10 @@ const validationRules = {
inboxId: { required },
};
const accountId = computed(() => {
return route.params.accountId || window.chatwootConfig?.account_id;
});
const inboxList = computed(() => {
const captainInboxIds = formState.captainInboxes.value.map(inbox => inbox.id);
@ -62,7 +67,8 @@ const isLoading = computed(() => formState.uiFlags.value.creatingItem);
const getErrorMessage = (field, errorKey) => {
return v$.value[field].$error
? t(`CAPTAIN.INBOXES.FORM.${errorKey}.ERROR`)
? // eslint-disable-next-line @intlify/vue-i18n/no-dynamic-keys
t(`CAPTAIN.INBOXES.FORM.${errorKey}.ERROR`)
: '';
};
@ -87,22 +93,36 @@ const handleSubmit = async () => {
emit('submit', prepareInboxPayload());
};
const accountId = useMapGetter('auth/getAccountId');
const fetchUnits = async () => {
if (!accountId.value) {
return;
}
if (!window.axios) {
return;
}
onMounted(async () => {
try {
const { data } = await axios.get(
`/api/v1/accounts/${accountId.value}/captain/units`
);
const url = `/api/v1/accounts/${accountId.value}/captain/units`;
const { data } = await window.axios.get(url);
units.push(...data);
} catch (error) {
// Silent fail or alert
// Ignore error
}
};
onMounted(() => {
fetchUnits();
});
watch(accountId, () => {
fetchUnits();
});
</script>
<template>
<!-- eslint-disable vue/no-bare-strings-in-template -->
<!-- eslint-disable @intlify/vue-i18n/no-raw-text -->
<form class="flex flex-col gap-4" @submit.prevent="handleSubmit">
<div class="flex flex-col gap-1">
<label for="inbox" class="mb-0.5 text-sm font-medium text-n-slate-12">
@ -122,6 +142,7 @@ onMounted(async () => {
<!-- Unit Selection -->
<div class="flex flex-col gap-1">
<label for="unit" class="mb-0.5 text-sm font-medium text-n-slate-12">
<!-- eslint-disable-next-line @intlify/vue-i18n/no-raw-text -->
Unidade (Opcional - Pix)
</label>
<ComboBox
@ -132,6 +153,7 @@ onMounted(async () => {
class="[&>div>button]:bg-n-alpha-black2 [&>div>button:not(.focused)]:dark:outline-n-weak [&>div>button:not(.focused)]:hover:!outline-n-slate-6"
/>
<span class="text-xs text-n-slate-11">
<!-- eslint-disable-next-line @intlify/vue-i18n/no-raw-text -->
Vincule a uma unidade para ativar Pix automático.
</span>
</div>

View File

@ -10,7 +10,7 @@ const props = defineProps({
type: {
type: String,
default: 'edit',
validator: value => ['alert', 'edit'].includes(value),
validator: value => ['alert', 'edit', 'create'].includes(value),
},
title: {
type: String,

View File

@ -49,3 +49,8 @@
title: 'Suite Watchdog'
description: 'Monitor suite availability and notify the customer when it becomes free'
icon: 'search'
- id: generate_pix
title: 'Gerar Pix'
description: 'Gera uma chave Copia e Cola do Pix para pagamento'
icon: 'bank-note'

View File

@ -448,7 +448,7 @@ ActiveRecord::Schema[7.1].define(version: 2026_01_14_101014) do
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.boolean "always_use_reminder_tool", default: false, null: false
t.bigint "captain_unit_id", null: false
t.bigint "captain_unit_id"
t.index ["captain_assistant_id", "inbox_id"], name: "index_captain_inboxes_on_captain_assistant_id_and_inbox_id", unique: true
t.index ["captain_assistant_id"], name: "index_captain_inboxes_on_captain_assistant_id"
t.index ["captain_unit_id"], name: "index_captain_inboxes_on_captain_unit_id"