10 KiB
10 KiB
🎨 Side Card - Guia de Implementação
✨ Visão Geral
O Side Card é uma nova funcionalidade que permite exibir um cartão lateral ao lado dos formulários de tabs, ideal para mostrar resumos, informações principais ou contexto adicional durante a edição de registros.
🏗️ Configuração Básica
1️⃣ Interface de Configuração
interface SideCardConfig {
enabled: boolean;
title: string;
position?: 'right' | 'left'; // Posição do card (padrão: 'right')
width?: string; // Largura do card (padrão: '300px')
component?: 'summary' | 'custom'; // Tipo de card (padrão: 'summary')
data?: {
imageField?: string; // Campo que contém a imagem principal
displayFields?: Array<{
key: string;
label: string;
type?: 'text' | 'currency' | 'status' | 'badge' | 'image';
format?: string; // Para formatação específica
}>;
statusField?: string; // Campo para status/badge
statusConfig?: {
[status: string]: {
label: string;
color: string;
icon?: string;
};
};
};
}
2️⃣ Configuração no TabFormConfig
const tabFormConfig: TabFormConfig = {
title: "Editar Veículo",
entityType: "vehicle",
fields: [
// ... seus campos do formulário
],
subTabs: [
{ id: 'dados', label: 'Dados Gerais', icon: 'fa-info-circle' },
{ id: 'multas', label: 'Multas', icon: 'fa-exclamation-triangle' },
{ id: 'rastreadores', label: 'Rastreadores', icon: 'fa-map-marked-alt' }
],
// ✨ Configuração do Side Card
sideCard: {
enabled: true,
title: "Resumo do Veículo",
position: "right",
width: "320px",
component: "summary",
data: {
imageField: "vehicle_image", // Campo da imagem principal
displayFields: [
{
key: "brand_model",
label: "Marca/Modelo",
type: "text",
format: "capitalize"
},
{
key: "license_plate",
label: "Placa",
type: "text",
format: "uppercase"
},
{
key: "year",
label: "Ano",
type: "text"
},
{
key: "mileage",
label: "Quilometragem",
type: "text"
},
{
key: "status",
label: "Status",
type: "status"
},
{
key: "driver_name",
label: "Motorista",
type: "text"
},
{
key: "fipe_value",
label: "Valor FIPE",
type: "currency"
}
],
statusField: "status",
statusConfig: {
"active": {
label: "Em operação",
color: "#10b981",
icon: "fa-check-circle"
},
"maintenance": {
label: "Manutenção",
color: "#f59e0b",
icon: "fa-wrench"
},
"inactive": {
label: "Inativo",
color: "#6b7280",
icon: "fa-pause-circle"
},
"repair": {
label: "Em reparo",
color: "#ef4444",
icon: "fa-tools"
}
}
}
}
};
🎯 Exemplos de Uso
📋 Exemplo 1: Card Simples de Motorista
const driverFormConfig: TabFormConfig = {
title: "Editar Motorista",
entityType: "driver",
fields: [/* campos do formulário */],
subTabs: [
{ id: 'dados', label: 'Dados Pessoais', icon: 'fa-user' },
{ id: 'endereco', label: 'Endereço', icon: 'fa-map-marker-alt' },
{ id: 'documentos', label: 'Documentos', icon: 'fa-file-alt' }
],
sideCard: {
enabled: true,
title: "Resumo do Motorista",
width: "280px",
data: {
imageField: "profile_photo",
displayFields: [
{
key: "full_name",
label: "Nome Completo",
type: "text"
},
{
key: "cpf",
label: "CPF",
type: "text"
},
{
key: "cnh_number",
label: "CNH",
type: "text"
},
{
key: "phone",
label: "Telefone",
type: "text"
},
{
key: "status",
label: "Status",
type: "status"
}
],
statusConfig: {
"active": { label: "Ativo", color: "#10b981" },
"inactive": { label: "Inativo", color: "#6b7280" },
"suspended": { label: "Suspenso", color: "#ef4444" }
}
}
}
};
💰 Exemplo 2: Card com Valores Financeiros
const contractFormConfig: TabFormConfig = {
title: "Editar Contrato",
entityType: "contract",
fields: [/* campos do formulário */],
sideCard: {
enabled: true,
title: "Resumo Financeiro",
position: "right",
width: "350px",
data: {
displayFields: [
{
key: "contract_number",
label: "Número do Contrato",
type: "text"
},
{
key: "client_name",
label: "Cliente",
type: "text"
},
{
key: "total_value",
label: "Valor Total",
type: "currency"
},
{
key: "monthly_payment",
label: "Parcela Mensal",
type: "currency"
},
{
key: "due_date",
label: "Vencimento",
type: "text",
format: "date"
},
{
key: "status",
label: "Status",
type: "status"
}
],
statusConfig: {
"active": { label: "Ativo", color: "#10b981", icon: "fa-check" },
"pending": { label: "Pendente", color: "#f59e0b", icon: "fa-clock" },
"overdue": { label: "Vencido", color: "#ef4444", icon: "fa-exclamation" }
}
}
}
};
🎨 Tipos de Campos Disponíveis
📝 text - Texto Simples
{
key: "name",
label: "Nome",
type: "text",
format: "capitalize" // opcional: "uppercase", "lowercase", "capitalize"
}
💰 currency - Valores Monetários
{
key: "price",
label: "Preço",
type: "currency" // Automaticamente formatado como R$ 1.234,56
}
🏷️ status - Status com Badge Colorido
{
key: "status",
label: "Status",
type: "status" // Usa a configuração de statusConfig
}
📅 Formatação de Data
{
key: "created_at",
label: "Criado em",
type: "text",
format: "date" // ou "datetime"
}
🎯 Configurações de Status
🎨 Cores Recomendadas
statusConfig: {
// ✅ Estados Positivos
"active": { label: "Ativo", color: "#10b981", icon: "fa-check-circle" },
"completed": { label: "Concluído", color: "#059669", icon: "fa-check" },
"approved": { label: "Aprovado", color: "#16a34a", icon: "fa-thumbs-up" },
// ⚠️ Estados de Atenção
"pending": { label: "Pendente", color: "#f59e0b", icon: "fa-clock" },
"maintenance": { label: "Manutenção", color: "#d97706", icon: "fa-wrench" },
"review": { label: "Em Análise", color: "#eab308", icon: "fa-search" },
// 🔴 Estados Críticos
"inactive": { label: "Inativo", color: "#6b7280", icon: "fa-pause-circle" },
"cancelled": { label: "Cancelado", color: "#dc2626", icon: "fa-times-circle" },
"error": { label: "Erro", color: "#ef4444", icon: "fa-exclamation-triangle" },
// 🔵 Estados Neutros
"draft": { label: "Rascunho", color: "#64748b", icon: "fa-edit" },
"scheduled": { label: "Agendado", color: "#0ea5e9", icon: "fa-calendar" }
}
📱 Responsividade
O Side Card é automaticamente responsivo:
- Desktop (>1200px): Card lateral fixo
- Tablet (768px-1200px): Card fica acima do formulário
- Mobile (<768px): Card em layout de coluna única
🔧 Quando Usar
✅ Recomendado para:
- Formulários de edição com dados existentes
- Exibir informações contextuais importantes
- Resumos visuais de entidades complexas
- Status e indicadores relevantes
❌ Não recomendado para:
- Formulários de criação (dados vazios)
- Formulários muito simples (poucas informações)
- Telas já sobrecarregadas visualmente
🚀 Exemplo Completo de Implementação
// No seu componente de domínio
private openTabForm(vehicle?: Vehicle) {
const config: TabFormConfig = {
title: vehicle ? "Editar Veículo" : "Novo Veículo",
entityType: "vehicle",
fields: [
{ key: "license_plate", label: "Placa", type: "text", required: true },
{ key: "brand", label: "Marca", type: "text", required: true },
{ key: "model", label: "Modelo", type: "text", required: true },
// ... outros campos
],
subTabs: [
{ id: 'dados', label: 'Dados Gerais', icon: 'fa-car' },
{ id: 'documentos', label: 'Documentos', icon: 'fa-file-alt' },
{ id: 'multas', label: 'Multas', icon: 'fa-exclamation-triangle' }
],
// ✨ Side Card aparece apenas quando editando
sideCard: vehicle ? {
enabled: true,
title: "Resumo do Veículo",
position: "right",
width: "300px",
component: "summary",
data: {
imageField: "main_photo",
displayFields: [
{ key: "brand_model", label: "Marca/Modelo", type: "text" },
{ key: "license_plate", label: "Placa", type: "text", format: "uppercase" },
{ key: "year", label: "Ano", type: "text" },
{ key: "status", label: "Status", type: "status" }
],
statusConfig: {
"active": { label: "Em operação", color: "#10b981", icon: "fa-check-circle" },
"inactive": { label: "Inativo", color: "#6b7280", icon: "fa-pause-circle" }
}
}
} : undefined
};
// Abrir o formulário com tab system
const tabRef = this.tabSystem.openTab({
id: vehicle?.id || 'new',
title: vehicle ? `Veículo: ${vehicle.license_plate}` : 'Novo Veículo',
type: 'vehicle',
data: vehicle,
config: config
});
}
🎉 Resultado
Com essa configuração, você terá:
- Layout responsivo com card lateral
- Imagem do veículo (ou placeholder se não houver)
- Informações principais bem organizadas
- Status colorido com ícones
- Valores formatados automaticamente
- Experiência consistente em todo o sistema
🚀 Próximos passos: Teste a funcionalidade, ajuste as configurações conforme necessário e aproveite a nova experiência de usuário!