Files
Investidor-V2/resources/js/components/search-usage-report.tsx
T

119 lines
5.3 KiB
TypeScript

import { usageValue, type SearchUsageReport } from '@/lib/product-usage';
import { card } from '@/pages/investment/shared';
export default function SearchUsage({ search }: { search: SearchUsageReport }) {
return (
<section
className={card + ' space-y-3'}
aria-labelledby="search-usage-title"
>
<h2 id="search-usage-title" className="text-xl font-semibold">
Pesquisas — respostas registadas
</h2>
<p>
Uma resposta HTTP de primeira página com critérios explícitos é
a unidade desta medição. Repetições e actualizações contam
novamente; pessoas, bots e pesquisas únicas não são
identificados.
</p>
<p>
Edição: {search.definition_version}. Dias {search.from} a{' '}
{search.to}, em {search.timezone}. Leitura em {search.read_at}.
As contagens diárias usam o snapshot do relatório; o dia actual
é parcial e não há corte por fracção de segundo.
</p>
{!search.installed && (
<p role="status">
Ainda não há dados de recolha disponíveis neste destino.
</p>
)}
{!search.enabled_now && (
<p role="status">
A recolha está desligada neste momento. O histórico
registado mantém-se disponível.
</p>
)}
{!search.applicable && (
<p role="status">
Estas pesquisas públicas não têm associação comprovada ao
serviço do Balcão seleccionado. Os valores não são
calculados para esse filtro.
</p>
)}
{search.definition_conflict_now && (
<p role="status">
A definição desta edição foi preservada. Uma configuração
diferente com o mesmo identificador não acrescenta contagens
a esta série.
</p>
)}
<p>
Respostas: {usageValue(search.responses)}. Sem resultados
principais: {usageValue(search.zero_responses)}. Taxa entre
respostas registadas: {usageValue(search.zero_rate, '%')}.
</p>
<p>
Cobertura parcial: falhas de recolha podem deixar respostas por
contar. Sem registos de medição não significa zero pesquisas.
</p>
<div className="overflow-x-auto">
<table className="w-full text-left">
<caption className="text-left font-semibold">
Canais públicos instrumentados nesta edição
</caption>
<thead>
<tr>
<th className="p-2">Canal</th>
<th className="p-2">Respostas</th>
<th className="p-2">Sem resultados principais</th>
<th className="p-2">Taxa na base registada</th>
<th className="p-2">
Primeira / última observação no período
</th>
</tr>
</thead>
<tbody>
{search.channels.map((channel) => (
<tr className="border-t align-top" key={channel.id}>
<th scope="row" className="p-2">
{channel.label}
</th>
<td className="p-2">
{usageValue(channel.responses)}
</td>
<td className="p-2">
{usageValue(channel.zero_responses)}
</td>
<td className="p-2">
{usageValue(channel.zero_rate, '%')}
</td>
<td className="p-2">
{channel.first_recorded_at ? (
<>
{channel.first_recorded_at}
<br />
{channel.last_recorded_at}
</>
) : (
'Sem registos'
)}
</td>
</tr>
))}
</tbody>
</table>
</div>
<details>
<summary className="cursor-pointer underline">
Âmbito, exclusões e interpretação
</summary>
<ul className="list-disc pl-5">
{[...search.limits, ...search.exclusions].map((text) => (
<li key={text}>{text}</li>
))}
</ul>
</details>
</section>
);
}