docs: adicionar exemplo de pipeline estilo trello

This commit is contained in:
Luiz Silva 2026-01-02 21:39:11 -03:00
parent 638fca78b0
commit ab15c51a1b

208
README.md
View file

@ -189,6 +189,214 @@ Alguns exemplos usam `<v-icon>` com Material Design Icons. O `eli-vue` **não in
- garanta que o seu projeto consumidor está configurado com o pacote de ícones desejado (ex.: MDI) - garanta que o seu projeto consumidor está configurado com o pacote de ícones desejado (ex.: MDI)
- ou substitua o conteúdo do slot por outro elemento - ou substitua o conteúdo do slot por outro elemento
## Exemplo de composição (pipeline estilo Trello)
O caso mais comum no **gestor de oportunidades e propostas comerciais** é compor UI a partir de componentes básicos.
Exemplo: um **pipeline** em colunas (estilo Trello/Kanban) com cards de oportunidades.
> Este exemplo usa Vuetify para layout/containers e o `eli-vue` para inputs, botões e indicadores.
```vue
<template>
<v-container class="py-6">
<div class="toolbar">
<h2 class="text-h6">Pipeline de Oportunidades</h2>
<EliInput
v-model="filtro"
label="Buscar"
placeholder="Cliente, proposta, valor..."
density="compact"
/>
<EliBotao @click="criarOportunidade">Nova oportunidade</EliBotao>
</div>
<div class="colunas">
<section
v-for="coluna in colunas"
:key="coluna.id"
class="coluna"
>
<header class="coluna-header">
<strong>{{ coluna.titulo }}</strong>
<EliBadge :badge="coluna.itens.length" radius="pill" />
</header>
<div class="cards">
<v-card
v-for="item in itensFiltrados(coluna.itens)"
:key="item.id"
class="card"
variant="outlined"
>
<v-card-title class="d-flex justify-space-between align-center">
<span class="text-subtitle-2">{{ item.titulo }}</span>
<EliBadge
v-if="item.alerta"
dot
color="error"
:visible="true"
>
<span />
</EliBadge>
</v-card-title>
<v-card-text class="text-body-2">
<div><strong>Cliente:</strong> {{ item.cliente }}</div>
<div><strong>Valor:</strong> {{ item.valor }}</div>
<div><strong>Vencimento:</strong> {{ item.vencimento }}</div>
</v-card-text>
<v-card-actions>
<EliBotao variant="text" @click="abrir(item)">Abrir</EliBotao>
<EliBotao variant="text" color="secondary" @click="editar(item)">
Editar
</EliBotao>
</v-card-actions>
</v-card>
</div>
</section>
</div>
</v-container>
</template>
<script lang="ts">
import { defineComponent, ref } from "vue";
import { EliBadge, EliBotao, EliInput } from "eli-vue";
type Oportunidade = {
id: string;
titulo: string;
cliente: string;
valor: string;
vencimento: string;
alerta?: boolean;
};
type Coluna = {
id: string;
titulo: string;
itens: Oportunidade[];
};
export default defineComponent({
name: "PipelineExemplo",
components: { EliBadge, EliBotao, EliInput },
setup() {
const filtro = ref("");
const colunas = ref<Coluna[]>([
{
id: "novo",
titulo: "Novo",
itens: [
{
id: "1",
titulo: "Proposta #1024",
cliente: "ACME Ltda",
valor: "R$ 12.500,00",
vencimento: "10/01/2026",
alerta: true,
},
],
},
{
id: "negociacao",
titulo: "Negociação",
itens: [
{
id: "2",
titulo: "Oportunidade #204",
cliente: "Empresa X",
valor: "R$ 8.000,00",
vencimento: "15/01/2026",
},
],
},
{
id: "ganho",
titulo: "Ganho",
itens: [],
},
]);
function itensFiltrados(itens: Oportunidade[]) {
const q = filtro.value.trim().toLowerCase();
if (!q) return itens;
return itens.filter((i) =>
`${i.titulo} ${i.cliente} ${i.valor}`.toLowerCase().includes(q)
);
}
function criarOportunidade() {
// aqui você abriria um modal / rota de criação
}
function abrir(item: Oportunidade) {
// aqui você navega para detalhes da oportunidade
}
function editar(item: Oportunidade) {
// aqui você abre edição
}
return {
filtro,
colunas,
itensFiltrados,
criarOportunidade,
abrir,
editar,
};
},
});
</script>
<style scoped>
.toolbar {
display: grid;
grid-template-columns: 1fr minmax(260px, 420px) auto;
gap: 12px;
align-items: center;
margin-bottom: 16px;
}
.colunas {
display: grid;
gap: 16px;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
}
.coluna {
border: 1px solid rgba(0, 0, 0, 0.12);
border-radius: 12px;
padding: 12px;
background: rgba(0, 0, 0, 0.02);
}
.coluna-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 12px;
}
.cards {
display: grid;
gap: 12px;
}
.card {
border-radius: 12px;
}
@media (max-width: 720px) {
.toolbar {
grid-template-columns: 1fr;
}
}
</style>
```
## Como rodar localmente ## Como rodar localmente
### Playground ### Playground