docs: adicionar exemplo de pipeline estilo trello
This commit is contained in:
parent
638fca78b0
commit
ab15c51a1b
1 changed files with 208 additions and 0 deletions
208
README.md
208
README.md
|
|
@ -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)
|
||||
- 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
|
||||
|
||||
### Playground
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue