ソースを参照

fix: corrige falha de ausencia de dados em avaliações de atendimentos

leonardo 1 ヶ月 前
コミット
d24d5bc2dc

+ 23 - 22
src/components/base/BaseDropdown.vue

@@ -2,14 +2,21 @@
   <div ref="raiz" class="relative shrink-0">
     <button
       type="button"
-      class="flex items-center gap-1 rounded-full border border-gray-200 px-3 py-1 text-xs font-medium text-gray-600 transition-colors hover:border-gray-300 dark:border-gray-700 dark:text-gray-300 dark:hover:border-gray-600"
-      :class="modelValue ? 'border-primary/40 bg-primary/10 text-primary dark:border-primary/40 dark:bg-primary/10 dark:text-primary' : ''"
+      class="flex items-center gap-1.5 rounded-lg border border-gray-300 bg-background px-3 py-1.5 text-sm text-gray-700 shadow-sm transition-colors hover:border-gray-400 focus:outline-none focus-visible:ring-2 focus-visible:ring-ring dark:border-gray-600 dark:text-gray-200 dark:hover:border-gray-500"
       :aria-expanded="aberto"
       aria-haspopup="listbox"
       @click="alternar"
     >
-      <span class="max-w-[120px] truncate">{{ rotuloAtual }}</span>
-      <svg class="h-3 w-3 shrink-0" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
+      <span class="text-gray-500 dark:text-gray-400">{{ rotulo }}</span>
+      <span class="max-w-[110px] truncate font-medium text-gray-900 dark:text-gray-100">{{ valorAtual }}</span>
+      <svg
+        class="h-3.5 w-3.5 shrink-0 text-gray-400 transition-transform dark:text-gray-500"
+        :class="aberto ? 'rotate-180' : ''"
+        viewBox="0 0 24 24"
+        fill="none"
+        stroke="currentColor"
+        stroke-width="2"
+      >
         <path stroke-linecap="round" stroke-linejoin="round" d="m19.5 8.25-7.5 7.5-7.5-7.5" />
       </svg>
     </button>
@@ -25,28 +32,18 @@
       <ul
         v-if="aberto"
         role="listbox"
-        class="absolute left-0 top-full z-20 mt-2 max-h-72 w-56 origin-top-left overflow-auto rounded-xl border border-gray-200 bg-background py-1 text-sm shadow-lg dark:border-gray-700"
+        class="absolute left-0 top-full z-20 mt-2 w-56 origin-top-left rounded-xl border border-gray-200 bg-background py-1.5 text-sm shadow-xl dark:border-gray-700"
       >
-        <li v-for="opt in opcoesComPadrao" :key="opt.value">
+        <li v-for="opt in opcoesComPadrao" :key="opt.value" class="px-1.5">
           <button
             type="button"
             role="option"
             :aria-selected="opt.value === modelValue"
-            class="flex w-full items-center justify-between gap-2 px-3 py-1.5 text-left hover:bg-black/[0.04] dark:hover:bg-white/[0.06]"
-            :class="opt.value === modelValue ? 'font-medium text-primary' : 'text-gray-700 dark:text-gray-200'"
+            class="w-full rounded-lg border-0 bg-transparent px-2.5 py-2 text-left text-gray-700 hover:bg-gray-200 dark:text-gray-200 dark:hover:bg-white/5"
+            :class="opt.value === modelValue ? 'bg-gray-200 dark:bg-white/5' : ''"
             @click="selecionar(opt.value)"
           >
             <span class="truncate">{{ opt.label }}</span>
-            <svg
-              v-if="opt.value === modelValue"
-              class="h-3.5 w-3.5 shrink-0"
-              viewBox="0 0 24 24"
-              fill="none"
-              stroke="currentColor"
-              stroke-width="2"
-            >
-              <path stroke-linecap="round" stroke-linejoin="round" d="m4.5 12.75 6 6 9-13.5" />
-            </svg>
           </button>
         </li>
       </ul>
@@ -68,14 +65,18 @@ const emit = defineEmits(["update:modelValue", "change"]);
 const aberto = ref(false);
 const raiz = ref(null);
 
+const rotuloPadraoCapitalizado = computed(
+  () => props.rotuloPadrao.charAt(0).toUpperCase() + props.rotuloPadrao.slice(1),
+);
+
 const opcoesComPadrao = computed(() => [
-  { value: "", label: `${props.rotulo}: ${props.rotuloPadrao}` },
+  { value: "", label: rotuloPadraoCapitalizado.value },
   ...props.opcoes,
 ]);
 
-const rotuloAtual = computed(() => {
-  const selecionada = opcoesComPadrao.value.find((o) => o.value === props.modelValue);
-  return selecionada ? selecionada.label : `${props.rotulo}: ${props.rotuloPadrao}`;
+const valorAtual = computed(() => {
+  const selecionada = props.opcoes.find((o) => o.value === props.modelValue);
+  return selecionada ? selecionada.label : rotuloPadraoCapitalizado.value;
 });
 
 function alternar() {

+ 7 - 0
src/utils/avaliacoes.js

@@ -13,3 +13,10 @@ export const sentimentoVariant = { positivo: "success", neutro: "default", negat
 export const sentimentoLabel = { positivo: "Positivo", neutro: "Neutro", negativo: "Negativo", indefinido: "Indefinido" };
 export const cancelamentoVariant = { cancelou: "danger", ameacou: "warning" };
 export const cancelamentoLabel = { cancelou: "Cancelou", ameacou: "Quer cancelar" };
+
+// só "erro" indica falha real na integração; sem_erp_protocolo/sem_ticket/nao_verificado são
+// desfechos esperados e não devem gerar alerta visual (ver design da change fix-ixc-contexto-falha-silenciosa)
+export const CONTEXTO_IXC_ERRO_LABEL = "Contexto do ERP indisponível nesta avaliação";
+export function contextoIxcFalhou(status) {
+  return status === "erro";
+}

+ 5 - 0
src/views/atendimentos/AtendimentoView.vue

@@ -8,6 +8,8 @@ import { obterAtendimento } from "../../api/atendimentos.js";
 import {
   cancelamentoLabel,
   cancelamentoVariant,
+  CONTEXTO_IXC_ERRO_LABEL,
+  contextoIxcFalhou,
   resolvidoLabel,
   resolvidoVariant,
   scoreVariant,
@@ -159,6 +161,9 @@ watch(() => route.params.id, carregar, { immediate: true });
               <BaseBadge v-if="cancelamentoLabel[avaliacao.StatusCancelamento]" :variant="cancelamentoVariant[avaliacao.StatusCancelamento]">
                 {{ cancelamentoLabel[avaliacao.StatusCancelamento] }}
               </BaseBadge>
+              <BaseBadge v-if="contextoIxcFalhou(avaliacao.ContextoIxcStatus)" variant="warning" :title="CONTEXTO_IXC_ERRO_LABEL">
+                Contexto ERP indisponível
+              </BaseBadge>
             </div>
           </div>
 

+ 5 - 0
src/views/atendimentos/AvaliacoesView.vue

@@ -14,6 +14,8 @@ import {
 import {
   cancelamentoLabel,
   cancelamentoVariant,
+  CONTEXTO_IXC_ERRO_LABEL,
+  contextoIxcFalhou,
   resolvidoLabel,
   resolvidoVariant,
   scoreVariant,
@@ -438,6 +440,9 @@ onBeforeUnmount(() => {
                 <BaseBadge v-if="cancelamentoLabel[a.StatusCancelamento]" :variant="cancelamentoVariant[a.StatusCancelamento]">
                   {{ cancelamentoLabel[a.StatusCancelamento] }}
                 </BaseBadge>
+                <BaseBadge v-if="contextoIxcFalhou(a.ContextoIxcStatus)" variant="warning" :title="CONTEXTO_IXC_ERRO_LABEL">
+                  Contexto ERP indisponível
+                </BaseBadge>
               </button>
 
               <div v-if="expandido === a.AtendimentoId" class="space-y-3 px-4 pb-4 text-sm">