Skip to content

Detalhe de registro ​

A tela de um registro só: o que ele é, em que situação está e o que a pessoa pode fazer com ele.

Quando usar ​

  • Ao abrir um item de uma lista: uma obra, um contrato, uma medição.
  • Quando o registro tem partes (dados, planilhas, equipe), cada uma ganha uma aba ou um cartão.
  • Quando há uma decisão a tomar (aprovar, devolver), ela vai numa coluna lateral, com o resumo.

Componentes ​

  • BasePage: o título é o nome do registro (o único h1), o subtitle dá o contexto e o slot actions recebe a situação e as ações.
  • BaseSummaryList: os pares de rótulo e valor. Valor vazio aparece como traço e é lido como "Não informado".
  • BaseCard: cada bloco do detalhe, com título.
  • BaseTabs: as partes do registro, quando são muitas para uma tela só.
  • BasePageAside: a coluna lateral de 360 px para resumo, histórico e decisão.
  • BaseBadge: a situação do registro.
  • BaseBreadcrumb: o caminho de volta à lista, quando o registro fica dois ou mais níveis abaixo do menu.
  • BasePageState: carregando e erro enquanto o registro não chega.

Texto ​

  • Título com o tipo e a identificação: "Contrato 012/2026", "Obra Fórum de Alegre".
  • Subtítulo com o contexto que falta: "Obra: Reforma do Fórum de Alegre".
  • Rótulos iguais aos do formulário do mesmo registro.
  • Ações com verbo e objeto: "Alterar contrato", "Enviar para aprovação".

Faça e não faça ​

FaçaNão faça
Mostrar a situação com um selo ao lado do título.Esconder a situação no meio dos dados.
Usar os mesmos rótulos do formulário.Chamar de "Valor global" no detalhe o que o formulário chama de "Valor inicial com BDI".
Pôr a decisão no topo da coluna lateral.Deixar o botão de aprovar no fim de uma página longa.

Código ​

vue
<script setup lang="ts">
import { computed, ref } from 'vue'
import { BaseBadge, BaseButton, BaseCard, BasePage, BasePageState, BaseSummaryList, BaseTabs, type SummaryItem } from '@lab-inovacao-tjes/design-system'

const props = defineProps<{ contract: Contract | null; failed: boolean; canEdit: boolean }>()
const emit = defineEmits<{ retry: []; edit: [] }>()
const tab = ref('data')
const tabs = [
  { id: 'data', label: 'Dados' },
  { id: 'sheets', label: 'Planilhas' },
]
const summary = computed<SummaryItem[]>(() => [
  { label: 'Empresa contratada', value: props.contract?.company },
  { label: 'Valor inicial com BDI', value: props.contract?.amountText },
  { label: 'Data do contrato', value: props.contract?.signedOnText },
])
</script>

<template>
  <BasePageState v-if="!props.contract" :status="props.failed ? 'error' : 'loading'" loading-label="Carregando o contrato" @retry="emit('retry')" />
  <BasePage v-else :title="`Contrato ${props.contract.number}`" :subtitle="`Obra: ${props.contract.workName}`">
    <template #actions>
      <BaseBadge tone="success">Em execução</BaseBadge>
    </template>
    <BaseTabs v-model="tab" :tabs="tabs" label="Partes do contrato">
      <template #data>
        <BaseCard title="Dados do contrato">
          <BaseSummaryList :items="summary" layout="inline" />
          <BaseButton v-if="props.canEdit" kind="secondary" icon="pencil" @click="emit('edit')">Alterar contrato</BaseButton>
        </BaseCard>
      </template>
      <template #sheets>
        <BaseCard title="Planilhas do contrato">…</BaseCard>
      </template>
    </BaseTabs>
  </BasePage>
</template>

Na tela de referência ​