feat(cartao): adicionar cards com status e playground tipo trello

This commit is contained in:
Luiz Silva 2026-01-02 21:48:24 -03:00
parent ab15c51a1b
commit 5bb6732b81
8 changed files with 438 additions and 2 deletions

View file

@ -5,6 +5,7 @@
<v-tabs v-model="aba" color="primary" density="comfortable">
<v-tab value="botao">Botão</v-tab>
<v-tab value="indicador">Indicador</v-tab>
<v-tab value="cartao">Cartão</v-tab>
<v-tab value="campo">Campo</v-tab>
<v-tab value="ola_mundo">Demo</v-tab>
</v-tabs>
@ -13,6 +14,7 @@
<BotaoPlayground v-if="aba === 'botao'" />
<IndicadorPlayground v-else-if="aba === 'indicador'" />
<CartaoPlayground v-else-if="aba === 'cartao'" />
<CampoPlayground v-else-if="aba === 'campo'" />
<OlaMundoPlayground v-else />
</v-container>
@ -22,6 +24,7 @@
import { defineComponent } from 'vue'
import BotaoPlayground from "./botao.playground.vue";
import IndicadorPlayground from "./indicador.playground.vue";
import CartaoPlayground from "./cartao.playground.vue";
import CampoPlayground from "./campo.playground.vue";
import OlaMundoPlayground from "./ola_mundo.playground.vue";
@ -30,12 +33,13 @@ export default defineComponent({
components: {
BotaoPlayground,
IndicadorPlayground,
CartaoPlayground,
CampoPlayground,
OlaMundoPlayground,
},
data() {
return {
aba: "botao" as "botao" | "indicador" | "campo" | "ola_mundo",
aba: "botao" as "botao" | "indicador" | "cartao" | "campo" | "ola_mundo",
};
}
})

View file

@ -0,0 +1,202 @@
<template>
<section class="stack">
<h2>EliCartao (pipeline)</h2>
<div class="toolbar">
<EliInput
v-model="filtro"
label="Buscar"
placeholder="Cliente, título, valor..."
density="compact"
/>
<EliBotao @click="criar">Novo card</EliBotao>
</div>
<div class="colunas">
<section v-for="coluna in colunas" :key="coluna.status" class="coluna">
<header class="coluna-header">
<strong class="text-subtitle-1">{{ coluna.titulo }}</strong>
<EliBadge :badge="coluna.itens.length" radius="pill" />
</header>
<div class="cards">
<EliCartao
v-for="item in itensFiltrados(coluna.itens)"
:key="item.id"
:titulo="item.titulo"
:status="coluna.status"
>
<div class="linha"><strong>Cliente:</strong> {{ item.cliente }}</div>
<div class="linha"><strong>Valor:</strong> {{ item.valor }}</div>
<div class="linha"><strong>Vencimento:</strong> {{ item.vencimento }}</div>
<template #acoes>
<EliBotao variant="text" @click="abrir(item)">Abrir</EliBotao>
<EliBotao variant="text" color="secondary" @click="editar(item)">
Editar
</EliBotao>
</template>
</EliCartao>
</div>
</section>
</div>
</section>
</template>
<script lang="ts">
import { defineComponent, ref } from "vue";
import { EliBadge } from "@/componentes/indicador";
import { EliBotao } from "@/componentes/botao";
import { EliInput } from "@/componentes/campo";
import { EliCartao } from "@/componentes/cartao";
import type { CartaoStatus } from "@/tipos";
type Card = {
id: string;
titulo: string;
cliente: string;
valor: string;
vencimento: string;
};
type Coluna = {
status: CartaoStatus;
titulo: string;
itens: Card[];
};
export default defineComponent({
name: "CartaoPlayground",
components: { EliBadge, EliBotao, EliInput, EliCartao },
setup() {
const filtro = ref("");
const colunas = ref<Coluna[]>([
{
status: "novo",
titulo: "Novo",
itens: [
{
id: "1",
titulo: "Proposta #1024",
cliente: "ACME Ltda",
valor: "R$ 12.500,00",
vencimento: "10/01/2026",
},
],
},
{
status: "rascunho",
titulo: "Rascunho",
itens: [
{
id: "2",
titulo: "Oportunidade #204",
cliente: "Empresa X",
valor: "R$ 8.000,00",
vencimento: "15/01/2026",
},
],
},
{
status: "vendido",
titulo: "Vendido",
itens: [],
},
{
status: "cancelado",
titulo: "Cancelado",
itens: [
{
id: "3",
titulo: "Proposta #999",
cliente: "Cliente Y",
valor: "R$ 3.200,00",
vencimento: "02/01/2026",
},
],
},
]);
function itensFiltrados(itens: Card[]) {
const q = filtro.value.trim().toLowerCase();
if (!q) return itens;
return itens.filter((i) =>
`${i.titulo} ${i.cliente} ${i.valor}`.toLowerCase().includes(q)
);
}
function criar() {
// Exemplo: criar card no status "novo"
colunas.value[0]?.itens.unshift({
id: String(Date.now()),
titulo: "Nova oportunidade",
cliente: "(definir)",
valor: "R$ 0,00",
vencimento: "--/--/----",
});
}
function abrir(_item: Card) {
// Navegar para detalhes
}
function editar(_item: Card) {
// Abrir modal/rota de edição
}
return { filtro, colunas, itensFiltrados, criar, abrir, editar };
},
});
</script>
<style scoped>
.stack {
display: grid;
gap: 16px;
}
.toolbar {
display: grid;
gap: 12px;
grid-template-columns: minmax(260px, 420px) auto;
align-items: center;
}
.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;
}
.linha {
margin-bottom: 4px;
}
@media (max-width: 720px) {
.toolbar {
grid-template-columns: 1fr;
}
}
</style>