feat(protese): marketplace transacional fatia 4 — avaliação, satisfação na nota e selo verificado
- A clínica avalia o laboratório (1-5★ + comentário) após a entrega (protese_avaliacao, 1 por OS, reavaliável). POST /protese/os/:id/avaliar; avaliação volta no GET detalhe. - Nota ScoreOdonto passa a combinar 0.6·operacional + 0.4·satisfação (estrelas) quando há avaliações. Selo "Verificado" (≥5 entregas). Exposto no marketplace (★nota · nº avaliações · Verificado) e nos indicadores do lab (KPI Satisfação). Helper notasScorePorProtetico unificado (dropdown + marketplace). - UI: seção "Avaliar o laboratório" na OS entregue (lado clínica); selo/avaliações no card do marketplace. - Correção de passagem: FileText/Star importados em ProteseView (FileText faltava desde a fatia 3). Validado em DEV: 6 entregas + 5★/3★ → nota 9.2, satisfação 4★, verificado (marketplace e indicadores). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import React, { useState, useEffect, useCallback } from 'react';
|
||||
import { BarChart3, RefreshCw, Clock, AlertTriangle, RotateCcw, PackageX, Award, CheckCircle2 } from 'lucide-react';
|
||||
import { BarChart3, RefreshCw, Clock, AlertTriangle, RotateCcw, PackageX, Award, CheckCircle2, BadgeCheck, Star } from 'lucide-react';
|
||||
import { HybridBackend } from '../services/backend.ts';
|
||||
import { PageHeader } from '../components/PageHeader.tsx';
|
||||
|
||||
@@ -41,9 +41,12 @@ export const LabIndicadoresView: React.FC = () => {
|
||||
<span className="text-2xl font-black leading-none mt-0.5">{temNota ? ind.nota.toFixed(1) : '—'}</span>
|
||||
</div>
|
||||
<div className="min-w-0">
|
||||
<h3 className="text-sm font-black text-gray-800 uppercase">Nota ScoreOdonto</h3>
|
||||
<div className="flex items-center gap-2 flex-wrap">
|
||||
<h3 className="text-sm font-black text-gray-800 uppercase">Nota ScoreOdonto</h3>
|
||||
{ind.verificado && <span className="text-[9px] font-black px-2 py-0.5 rounded-full bg-teal-100 text-teal-700 uppercase flex items-center gap-0.5"><BadgeCheck size={11} /> Verificado</span>}
|
||||
</div>
|
||||
{temNota ? (
|
||||
<p className="text-[11px] text-gray-400 font-bold uppercase mt-1">Calculada sobre {ind.entregues} entrega(s). Penaliza atraso, retrabalho e ocorrências resolvidas.</p>
|
||||
<p className="text-[11px] text-gray-400 font-bold uppercase mt-1">Sobre {ind.entregues} entrega(s){ind.avaliacoes ? ` · ${ind.satisfacao}★ de ${ind.avaliacoes} avaliações` : ''}. Combina desempenho (atraso/retrabalho/ocorrências) e satisfação da clínica.</p>
|
||||
) : (
|
||||
<p className="text-[11px] text-amber-500 font-bold uppercase mt-1">Score em formação — mínimo de {ind.min_os} entregas para gerar a nota.</p>
|
||||
)}
|
||||
@@ -57,6 +60,7 @@ export const LabIndicadoresView: React.FC = () => {
|
||||
<KPI titulo="Retrabalho" valor={`${ind.retrabalho_pct}%`} cor="text-orange-500" Icon={RotateCcw} sub={`${ind.garantia} garantia(s)`} />
|
||||
<KPI titulo="Ocorrências" valor={`${ind.ocorrencia_pct}%`} cor="text-red-500" Icon={AlertTriangle} sub={`${ind.ocorrencias_resolvidas} resolvida(s)`} />
|
||||
<KPI titulo="Componentes perdidos" valor={String(ind.componentes_ausentes)} cor="text-red-600" Icon={PackageX} sub="Conferidos como ausentes" />
|
||||
<KPI titulo="Satisfação" valor={ind.satisfacao != null ? `${ind.satisfacao}★` : '—'} cor="text-amber-500" Icon={Star} sub={`${ind.avaliacoes || 0} avaliação(ões)`} />
|
||||
</div>
|
||||
|
||||
<div className="bg-white rounded-2xl border border-gray-100 shadow-sm p-5">
|
||||
|
||||
Reference in New Issue
Block a user