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)
|
- 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
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue