|
|
@@ -4,8 +4,9 @@ import { useRoute, useRouter } from "vue-router";
|
|
|
import LayoutSistema from "../../layout/LayoutSistema.vue";
|
|
|
import BaseBadge from "../../components/base/BaseBadge.vue";
|
|
|
import BaseButton from "../../components/base/BaseButton.vue";
|
|
|
+import ChatBubble from "../../components/base/ChatBubble.vue";
|
|
|
import ModalMidia from "../../components/ModalMidia.vue";
|
|
|
-import { obterAtendimento, salvarGoldenLabel, sincronizarAtendimento, avaliarAtendimento } from "../../api/atendimentos.js";
|
|
|
+import { obterAtendimento, salvarGoldenLabel, aceitarGoldenLabelComoIa, sincronizarAtendimento, avaliarAtendimento } from "../../api/atendimentos.js";
|
|
|
import { useAuth } from "../../composables/useAuth.js";
|
|
|
import {
|
|
|
cancelamentoLabel,
|
|
|
@@ -97,9 +98,25 @@ async function salvarRotulo() {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-// volta para a lista de origem (Avaliações ou Não resolvidos) preservando página, filtros
|
|
|
-// e item aberto (guardados na query string da rota anterior); se o gestor chegou por link
|
|
|
-// direto, não há histórico para voltar — vai para a lista de avaliações limpa
|
|
|
+const aceitando = ref(false);
|
|
|
+
|
|
|
+
|
|
|
+async function aceitarComoIa() {
|
|
|
+ if (aceitando.value || salvando.value || !atendimento.value) return;
|
|
|
+ aceitando.value = true;
|
|
|
+ try {
|
|
|
+ const atualizado = await aceitarGoldenLabelComoIa(atendimento.value.Id);
|
|
|
+ atendimento.value = { ...atendimento.value, goldenLabel: atualizado };
|
|
|
+ form.value = criarFormulario(atualizado);
|
|
|
+ toast.sucesso("Avaliação da IA aceita como rótulo.");
|
|
|
+ } catch (err) {
|
|
|
+ toast.erro(err?.message ?? "Falha ao aceitar a avaliação da IA.");
|
|
|
+ } finally {
|
|
|
+ aceitando.value = false;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
const ROTAS_ORIGEM = ["/atendimentos/avaliacoes", "/atendimentos/nao-resolvidos", "/atendimentos/golden-set"];
|
|
|
|
|
|
function voltar() {
|
|
|
@@ -240,13 +257,13 @@ watch(() => route.params.id, carregar, { immediate: true });
|
|
|
</svg>
|
|
|
</button>
|
|
|
<div class="min-w-0">
|
|
|
- <h2 class="text-base font-semibold text-gray-900 dark:text-gray-100">
|
|
|
+ <h2 class="text-base font-semibold text-foreground">
|
|
|
{{ atendimento?.Codigo ?? `Atendimento #${route.params.id}` }}
|
|
|
- <span v-if="atendimento?.cliente?.Nome" class="font-normal text-gray-500 dark:text-gray-400">
|
|
|
+ <span v-if="atendimento?.cliente?.Nome" class="font-normal text-muted-foreground">
|
|
|
— {{ atendimento.cliente.Nome }}
|
|
|
</span>
|
|
|
</h2>
|
|
|
- <p v-if="atendimento" class="mt-0.5 text-sm text-gray-500 dark:text-gray-400">
|
|
|
+ <p v-if="atendimento" class="mt-0.5 text-sm text-muted-foreground">
|
|
|
<span v-if="atendimento.Setor">{{ atendimento.Setor }} · </span>{{ formatData(atendimento.Abertura) }}
|
|
|
· {{ mensagens.length }} mensagens
|
|
|
</p>
|
|
|
@@ -291,12 +308,12 @@ watch(() => route.params.id, carregar, { immediate: true });
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
- <p v-if="avaliacao?.Resumo" class="mt-4 text-sm text-gray-600 dark:text-gray-300">
|
|
|
- <span class="text-xs font-semibold uppercase tracking-wide text-gray-400 dark:text-gray-500">Resumo da IA: </span>
|
|
|
+ <p v-if="avaliacao?.Resumo" class="mt-4 text-sm text-muted-foreground">
|
|
|
+ <span class="text-xs font-semibold uppercase tracking-wide text-muted-foreground">Resumo da IA: </span>
|
|
|
{{ avaliacao.Resumo }}
|
|
|
</p>
|
|
|
- <p v-if="avaliacao?.MotivoCancelamento" class="mt-1 text-sm text-gray-600 dark:text-gray-300">
|
|
|
- <span class="text-xs font-semibold uppercase tracking-wide text-gray-400 dark:text-gray-500">Motivo do cancelamento: </span>
|
|
|
+ <p v-if="avaliacao?.MotivoCancelamento" class="mt-1 text-sm text-muted-foreground">
|
|
|
+ <span class="text-xs font-semibold uppercase tracking-wide text-muted-foreground">Motivo do cancelamento: </span>
|
|
|
{{ avaliacao.MotivoCancelamento }}
|
|
|
</p>
|
|
|
</section>
|
|
|
@@ -306,11 +323,11 @@ watch(() => route.params.id, carregar, { immediate: true });
|
|
|
Conversa completa
|
|
|
</div>
|
|
|
|
|
|
- <div v-if="carregando" class="p-6 text-sm text-gray-500 dark:text-gray-400">Carregando conversa...</div>
|
|
|
+ <div v-if="carregando" class="p-6 text-sm text-muted-foreground">Carregando conversa...</div>
|
|
|
<div v-else-if="erro" class="m-4 rounded-lg bg-red-50 px-4 py-3 text-xs text-red-800 dark:bg-red-900/30 dark:text-red-300">
|
|
|
{{ erro }}
|
|
|
</div>
|
|
|
- <div v-else-if="mensagens.length === 0" class="p-6 text-sm text-gray-500 dark:text-gray-400">
|
|
|
+ <div v-else-if="mensagens.length === 0" class="p-6 text-sm text-muted-foreground">
|
|
|
Este atendimento não tem mensagens com conteúdo para exibir.
|
|
|
</div>
|
|
|
|
|
|
@@ -323,37 +340,29 @@ watch(() => route.params.id, carregar, { immediate: true });
|
|
|
</div>
|
|
|
|
|
|
<div v-if="m.Papel === 'sistema'" class="flex justify-center">
|
|
|
- <div class="max-w-[85%] px-3 py-1 text-center text-xs italic text-gray-400 dark:text-gray-500">
|
|
|
+ <div class="max-w-[85%] px-3 py-1 text-center text-xs italic text-muted-foreground">
|
|
|
{{ m.Texto }}<span v-if="formatHora(m.Timestamp)"> · {{ formatHora(m.Timestamp) }}</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
- <div v-else class="flex" :class="m.Papel === 'atendente' ? 'justify-end' : 'justify-start'">
|
|
|
- <div
|
|
|
- class="max-w-[75%] rounded-2xl px-3.5 py-2 shadow-sm"
|
|
|
- :class="
|
|
|
- m.Papel === 'atendente'
|
|
|
- ? 'rounded-br-sm bg-primary/10 dark:bg-primary/20'
|
|
|
- : 'rounded-bl-sm bg-gray-100 dark:bg-gray-800'
|
|
|
- "
|
|
|
- >
|
|
|
+ <ChatBubble v-else :own="m.Papel === 'atendente'">
|
|
|
<div
|
|
|
class="text-xs font-semibold"
|
|
|
- :class="m.Papel === 'atendente' ? 'text-primary' : 'text-gray-500 dark:text-gray-400'"
|
|
|
+ :class="m.Papel === 'atendente' ? 'text-primary' : 'text-muted-foreground'"
|
|
|
>
|
|
|
{{ autorLabel(m) }}
|
|
|
</div>
|
|
|
<template v-if="ehAudio(m)">
|
|
|
- <div class="mt-1 flex items-center gap-1.5 text-xs font-medium text-gray-500 dark:text-gray-400">
|
|
|
+ <div class="mt-1 flex items-center gap-1.5 text-xs font-medium text-muted-foreground">
|
|
|
<svg class="h-3.5 w-3.5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8">
|
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M12 18.75a6 6 0 0 0 6-6v-1.5m-6 7.5a6 6 0 0 1-6-6v-1.5m6 7.5v3.75m-3.75 0h7.5M12 15.75a3 3 0 0 1-3-3V4.5a3 3 0 1 1 6 0v8.25a3 3 0 0 1-3 3Z" />
|
|
|
</svg>
|
|
|
Mensagem de áudio
|
|
|
</div>
|
|
|
- <p v-if="m.Transcricao" class="mt-1 whitespace-pre-wrap break-words text-sm text-gray-800 dark:text-gray-200">
|
|
|
+ <p v-if="m.Transcricao" class="mt-1 whitespace-pre-wrap break-words text-sm text-foreground">
|
|
|
{{ m.Transcricao }}
|
|
|
</p>
|
|
|
- <p v-else class="mt-1 text-sm italic text-gray-400 dark:text-gray-500">Sem transcrição disponível</p>
|
|
|
+ <p v-else class="mt-1 text-sm italic text-muted-foreground">Sem transcrição disponível</p>
|
|
|
<audio v-if="m.MidiaUrl" controls preload="none" :src="m.MidiaUrl" class="mt-1.5 h-9 w-64 max-w-full"></audio>
|
|
|
<div
|
|
|
v-else-if="caminhoMidia(m)"
|
|
|
@@ -388,7 +397,7 @@ watch(() => route.params.id, carregar, { immediate: true });
|
|
|
</div>
|
|
|
</div>
|
|
|
</template>
|
|
|
- <p v-else class="mt-0.5 whitespace-pre-wrap break-words text-sm text-gray-800 dark:text-gray-200">{{ m.Texto }}</p>
|
|
|
+ <p v-else class="mt-0.5 whitespace-pre-wrap break-words text-sm text-foreground">{{ m.Texto }}</p>
|
|
|
<a
|
|
|
v-if="midiaLink(m)"
|
|
|
:href="midiaLink(m)"
|
|
|
@@ -398,9 +407,8 @@ watch(() => route.params.id, carregar, { immediate: true });
|
|
|
>
|
|
|
Abrir mídia
|
|
|
</a>
|
|
|
- <div class="mt-0.5 text-right text-[10px] text-gray-400 dark:text-gray-500">{{ formatHora(m.Timestamp) }}</div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
+ <div class="mt-0.5 text-right text-[10px] text-muted-foreground">{{ formatHora(m.Timestamp) }}</div>
|
|
|
+ </ChatBubble>
|
|
|
</template>
|
|
|
</div>
|
|
|
</section>
|
|
|
@@ -410,15 +418,17 @@ watch(() => route.params.id, carregar, { immediate: true });
|
|
|
class="rounded-2xl border border-gray-200 bg-background/70 shadow-sm dark:border-gray-700 dark:bg-background/20"
|
|
|
>
|
|
|
<div class="flex items-center justify-between gap-3 border-b border-gray-200 px-4 py-3 dark:border-gray-700">
|
|
|
- <div class="text-sm font-semibold text-gray-900 dark:text-gray-100">Rotulagem manual (golden set)</div>
|
|
|
- <BaseBadge :variant="goldenLabel.Status === 'rotulado' ? 'success' : 'warning'">
|
|
|
- {{ goldenLabel.Status === "rotulado" ? "Rotulado" : "Pendente" }}
|
|
|
+ <div class="text-sm font-semibold text-foreground">Rotulagem manual (golden set)</div>
|
|
|
+ <BaseBadge
|
|
|
+ :variant="goldenLabel.Status === 'rotulado' ? 'success' : goldenLabel.Status === 'aceito' ? 'info' : 'warning'"
|
|
|
+ >
|
|
|
+ {{ goldenLabel.Status === "rotulado" ? "Rotulado" : goldenLabel.Status === "aceito" ? "Aceito (IA)" : "Pendente" }}
|
|
|
</BaseBadge>
|
|
|
</div>
|
|
|
|
|
|
<div class="grid grid-cols-1 gap-5 p-4 sm:grid-cols-2">
|
|
|
<div>
|
|
|
- <label class="text-xs font-semibold uppercase tracking-wide text-gray-400 dark:text-gray-500">
|
|
|
+ <label class="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
|
|
|
Nota do atendente (1-10)
|
|
|
</label>
|
|
|
<div class="mt-1 flex items-center gap-2">
|
|
|
@@ -430,18 +440,18 @@ watch(() => route.params.id, carregar, { immediate: true });
|
|
|
:disabled="form.SemAtendente"
|
|
|
class="w-24 rounded-lg border border-gray-200 bg-background px-3 py-1.5 text-sm text-gray-700 focus:outline-none focus:ring-2 focus:ring-primary/30 disabled:opacity-50 dark:border-gray-700 dark:text-gray-200"
|
|
|
/>
|
|
|
- <label class="flex items-center gap-1.5 text-xs text-gray-500 dark:text-gray-400">
|
|
|
+ <label class="flex items-center gap-1.5 text-xs text-muted-foreground">
|
|
|
<input v-model="form.SemAtendente" type="checkbox" class="rounded" />
|
|
|
Sem atendente humano
|
|
|
</label>
|
|
|
</div>
|
|
|
- <span class="mt-1 block text-xs text-gray-400 dark:text-gray-500">
|
|
|
+ <span class="mt-1 block text-xs text-muted-foreground">
|
|
|
IA: {{ avaliacao?.ScoreAtendente ?? "sem nota" }}
|
|
|
</span>
|
|
|
</div>
|
|
|
|
|
|
<div>
|
|
|
- <label class="text-xs font-semibold uppercase tracking-wide text-gray-400 dark:text-gray-500">Resolvido</label>
|
|
|
+ <label class="text-xs font-semibold uppercase tracking-wide text-muted-foreground">Resolvido</label>
|
|
|
<select
|
|
|
v-model="form.Resolvido"
|
|
|
class="mt-1 w-full rounded-lg border border-gray-200 bg-background px-3 py-1.5 text-sm text-gray-700 focus:outline-none focus:ring-2 focus:ring-primary/30 dark:border-gray-700 dark:text-gray-200"
|
|
|
@@ -449,13 +459,13 @@ watch(() => route.params.id, carregar, { immediate: true });
|
|
|
<option value="">-- não rotulado --</option>
|
|
|
<option v-for="(label, value) in resolvidoLabel" :key="value" :value="value">{{ label }}</option>
|
|
|
</select>
|
|
|
- <span class="mt-1 block text-xs text-gray-400 dark:text-gray-500">
|
|
|
+ <span class="mt-1 block text-xs text-muted-foreground">
|
|
|
IA: {{ resolvidoLabel[avaliacao?.Resolvido] ?? "—" }}
|
|
|
</span>
|
|
|
</div>
|
|
|
|
|
|
<div>
|
|
|
- <label class="text-xs font-semibold uppercase tracking-wide text-gray-400 dark:text-gray-500">Sentimento do cliente</label>
|
|
|
+ <label class="text-xs font-semibold uppercase tracking-wide text-muted-foreground">Sentimento do cliente</label>
|
|
|
<select
|
|
|
v-model="form.Sentimento"
|
|
|
class="mt-1 w-full rounded-lg border border-gray-200 bg-background px-3 py-1.5 text-sm text-gray-700 focus:outline-none focus:ring-2 focus:ring-primary/30 dark:border-gray-700 dark:text-gray-200"
|
|
|
@@ -463,13 +473,13 @@ watch(() => route.params.id, carregar, { immediate: true });
|
|
|
<option value="">-- não rotulado --</option>
|
|
|
<option v-for="(label, value) in sentimentoLabel" :key="value" :value="value">{{ label }}</option>
|
|
|
</select>
|
|
|
- <span class="mt-1 block text-xs text-gray-400 dark:text-gray-500">
|
|
|
+ <span class="mt-1 block text-xs text-muted-foreground">
|
|
|
IA: {{ sentimentoLabel[avaliacao?.Sentimento] ?? "—" }}
|
|
|
</span>
|
|
|
</div>
|
|
|
|
|
|
<div>
|
|
|
- <label class="text-xs font-semibold uppercase tracking-wide text-gray-400 dark:text-gray-500">Cancelamento</label>
|
|
|
+ <label class="text-xs font-semibold uppercase tracking-wide text-muted-foreground">Cancelamento</label>
|
|
|
<select
|
|
|
v-model="form.StatusCancelamento"
|
|
|
class="mt-1 w-full rounded-lg border border-gray-200 bg-background px-3 py-1.5 text-sm text-gray-700 focus:outline-none focus:ring-2 focus:ring-primary/30 dark:border-gray-700 dark:text-gray-200"
|
|
|
@@ -477,13 +487,13 @@ watch(() => route.params.id, carregar, { immediate: true });
|
|
|
<option value="">-- não rotulado --</option>
|
|
|
<option v-for="(label, value) in statusCancelamentoLabel" :key="value" :value="value">{{ label }}</option>
|
|
|
</select>
|
|
|
- <span class="mt-1 block text-xs text-gray-400 dark:text-gray-500">
|
|
|
+ <span class="mt-1 block text-xs text-muted-foreground">
|
|
|
IA: {{ cancelamentoLabel[avaliacao?.StatusCancelamento] ?? "Não" }}
|
|
|
</span>
|
|
|
</div>
|
|
|
|
|
|
<div>
|
|
|
- <label class="text-xs font-semibold uppercase tracking-wide text-gray-400 dark:text-gray-500">Visita agendada</label>
|
|
|
+ <label class="text-xs font-semibold uppercase tracking-wide text-muted-foreground">Visita agendada</label>
|
|
|
<select
|
|
|
v-model="form.VisitaAgendada"
|
|
|
class="mt-1 w-full rounded-lg border border-gray-200 bg-background px-3 py-1.5 text-sm text-gray-700 focus:outline-none focus:ring-2 focus:ring-primary/30 dark:border-gray-700 dark:text-gray-200"
|
|
|
@@ -492,13 +502,13 @@ watch(() => route.params.id, carregar, { immediate: true });
|
|
|
<option value="sim">Sim</option>
|
|
|
<option value="nao">Não</option>
|
|
|
</select>
|
|
|
- <span class="mt-1 block text-xs text-gray-400 dark:text-gray-500">
|
|
|
+ <span class="mt-1 block text-xs text-muted-foreground">
|
|
|
IA: {{ avaliacao?.VisitaAgendada === true ? "Sim" : avaliacao?.VisitaAgendada === false ? "Não" : "—" }}
|
|
|
</span>
|
|
|
</div>
|
|
|
|
|
|
<div>
|
|
|
- <label class="text-xs font-semibold uppercase tracking-wide text-gray-400 dark:text-gray-500">Horário de visita informado</label>
|
|
|
+ <label class="text-xs font-semibold uppercase tracking-wide text-muted-foreground">Horário de visita informado</label>
|
|
|
<select
|
|
|
v-model="form.HorarioVisitaInformado"
|
|
|
class="mt-1 w-full rounded-lg border border-gray-200 bg-background px-3 py-1.5 text-sm text-gray-700 focus:outline-none focus:ring-2 focus:ring-primary/30 dark:border-gray-700 dark:text-gray-200"
|
|
|
@@ -506,24 +516,24 @@ watch(() => route.params.id, carregar, { immediate: true });
|
|
|
<option value="">-- não rotulado --</option>
|
|
|
<option v-for="(label, value) in HORARIO_VISITA_INFORMADO_LABEL" :key="value" :value="value">{{ label }}</option>
|
|
|
</select>
|
|
|
- <span class="mt-1 block text-xs text-gray-400 dark:text-gray-500">
|
|
|
+ <span class="mt-1 block text-xs text-muted-foreground">
|
|
|
IA: {{ HORARIO_VISITA_INFORMADO_LABEL[avaliacao?.HorarioVisitaInformado] ?? "—" }}
|
|
|
</span>
|
|
|
</div>
|
|
|
|
|
|
<div>
|
|
|
- <label class="text-xs font-semibold uppercase tracking-wide text-gray-400 dark:text-gray-500">Horário da visita</label>
|
|
|
+ <label class="text-xs font-semibold uppercase tracking-wide text-muted-foreground">Horário da visita</label>
|
|
|
<input
|
|
|
v-model="form.HorarioVisita"
|
|
|
type="text"
|
|
|
:disabled="form.HorarioVisitaInformado !== 'sim'"
|
|
|
class="mt-1 w-full rounded-lg border border-gray-200 bg-background px-3 py-1.5 text-sm text-gray-700 focus:outline-none focus:ring-2 focus:ring-primary/30 disabled:opacity-50 dark:border-gray-700 dark:text-gray-200"
|
|
|
/>
|
|
|
- <span class="mt-1 block text-xs text-gray-400 dark:text-gray-500">IA: {{ avaliacao?.HorarioVisita || "—" }}</span>
|
|
|
+ <span class="mt-1 block text-xs text-muted-foreground">IA: {{ avaliacao?.HorarioVisita || "—" }}</span>
|
|
|
</div>
|
|
|
|
|
|
<div>
|
|
|
- <label class="text-xs font-semibold uppercase tracking-wide text-gray-400 dark:text-gray-500">
|
|
|
+ <label class="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
|
|
|
Atendentes (separados por vírgula)
|
|
|
</label>
|
|
|
<input
|
|
|
@@ -531,35 +541,35 @@ watch(() => route.params.id, carregar, { immediate: true });
|
|
|
type="text"
|
|
|
class="mt-1 w-full rounded-lg border border-gray-200 bg-background px-3 py-1.5 text-sm text-gray-700 focus:outline-none focus:ring-2 focus:ring-primary/30 dark:border-gray-700 dark:text-gray-200"
|
|
|
/>
|
|
|
- <span class="mt-1 block text-xs text-gray-400 dark:text-gray-500">
|
|
|
+ <span class="mt-1 block text-xs text-muted-foreground">
|
|
|
IA: {{ avaliacao?.Atendentes?.join(", ") || "—" }}
|
|
|
</span>
|
|
|
</div>
|
|
|
|
|
|
<div class="sm:col-span-2">
|
|
|
- <label class="text-xs font-semibold uppercase tracking-wide text-gray-400 dark:text-gray-500">Justificativa da nota</label>
|
|
|
+ <label class="text-xs font-semibold uppercase tracking-wide text-muted-foreground">Justificativa da nota</label>
|
|
|
<textarea
|
|
|
v-model="form.JustificativaScore"
|
|
|
rows="2"
|
|
|
class="mt-1 w-full rounded-lg border border-gray-200 bg-background px-3 py-1.5 text-sm text-gray-700 focus:outline-none focus:ring-2 focus:ring-primary/30 dark:border-gray-700 dark:text-gray-200"
|
|
|
></textarea>
|
|
|
- <p v-if="avaliacao?.JustificativaScore" class="mt-1 text-xs text-gray-400 dark:text-gray-500">
|
|
|
+ <p v-if="avaliacao?.JustificativaScore" class="mt-1 text-xs text-muted-foreground">
|
|
|
IA: {{ avaliacao.JustificativaScore }}
|
|
|
</p>
|
|
|
</div>
|
|
|
|
|
|
<div class="sm:col-span-2">
|
|
|
- <label class="text-xs font-semibold uppercase tracking-wide text-gray-400 dark:text-gray-500">Resumo</label>
|
|
|
+ <label class="text-xs font-semibold uppercase tracking-wide text-muted-foreground">Resumo</label>
|
|
|
<textarea
|
|
|
v-model="form.Resumo"
|
|
|
rows="3"
|
|
|
class="mt-1 w-full rounded-lg border border-gray-200 bg-background px-3 py-1.5 text-sm text-gray-700 focus:outline-none focus:ring-2 focus:ring-primary/30 dark:border-gray-700 dark:text-gray-200"
|
|
|
></textarea>
|
|
|
- <p v-if="avaliacao?.Resumo" class="mt-1 text-xs text-gray-400 dark:text-gray-500">IA: {{ avaliacao.Resumo }}</p>
|
|
|
+ <p v-if="avaliacao?.Resumo" class="mt-1 text-xs text-muted-foreground">IA: {{ avaliacao.Resumo }}</p>
|
|
|
</div>
|
|
|
|
|
|
<div class="sm:col-span-2">
|
|
|
- <label class="text-xs font-semibold uppercase tracking-wide text-gray-400 dark:text-gray-500">
|
|
|
+ <label class="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
|
|
|
Sugestões de melhoria (uma por linha)
|
|
|
</label>
|
|
|
<textarea
|
|
|
@@ -567,26 +577,29 @@ watch(() => route.params.id, carregar, { immediate: true });
|
|
|
rows="3"
|
|
|
class="mt-1 w-full rounded-lg border border-gray-200 bg-background px-3 py-1.5 text-sm text-gray-700 focus:outline-none focus:ring-2 focus:ring-primary/30 dark:border-gray-700 dark:text-gray-200"
|
|
|
></textarea>
|
|
|
- <p v-if="avaliacao?.Sugestoes?.length" class="mt-1 text-xs text-gray-400 dark:text-gray-500">
|
|
|
+ <p v-if="avaliacao?.Sugestoes?.length" class="mt-1 text-xs text-muted-foreground">
|
|
|
IA: {{ avaliacao.Sugestoes.join(" · ") }}
|
|
|
</p>
|
|
|
</div>
|
|
|
|
|
|
<div class="sm:col-span-2">
|
|
|
- <label class="text-xs font-semibold uppercase tracking-wide text-gray-400 dark:text-gray-500">Motivo do cancelamento</label>
|
|
|
+ <label class="text-xs font-semibold uppercase tracking-wide text-muted-foreground">Motivo do cancelamento</label>
|
|
|
<textarea
|
|
|
v-model="form.MotivoCancelamento"
|
|
|
rows="2"
|
|
|
class="mt-1 w-full rounded-lg border border-gray-200 bg-background px-3 py-1.5 text-sm text-gray-700 focus:outline-none focus:ring-2 focus:ring-primary/30 dark:border-gray-700 dark:text-gray-200"
|
|
|
></textarea>
|
|
|
- <p v-if="avaliacao?.MotivoCancelamento" class="mt-1 text-xs text-gray-400 dark:text-gray-500">
|
|
|
+ <p v-if="avaliacao?.MotivoCancelamento" class="mt-1 text-xs text-muted-foreground">
|
|
|
IA: {{ avaliacao.MotivoCancelamento }}
|
|
|
</p>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<div class="flex items-center justify-end gap-3 border-t border-gray-200 px-4 py-3 dark:border-gray-700">
|
|
|
- <BaseButton :loading="salvando" @click="salvarRotulo">
|
|
|
+ <BaseButton variant="secondary" :loading="aceitando" :disabled="salvando" @click="aceitarComoIa">
|
|
|
+ {{ aceitando ? "Aceitando..." : "Concordo com a IA, deixar assim" }}
|
|
|
+ </BaseButton>
|
|
|
+ <BaseButton :loading="salvando" :disabled="aceitando" @click="salvarRotulo">
|
|
|
{{ salvando ? "Salvando..." : "Salvar rótulo" }}
|
|
|
</BaseButton>
|
|
|
</div>
|