Files
agenciapsilmno/src/features/agenda/components/cards/AgendaPulseCardGrid.vue
Leonardo f733db8436 ZERADO
2026-03-06 06:37:13 -03:00

138 lines
4.8 KiB
Vue

<!-- src/features/agenda/components/cards/AgendaPulseCardGrid.vue -->
<script setup>
import { computed } from 'vue'
const props = defineProps({
stats: { type: Object, default: () => ({}) }
})
const emit = defineEmits(['quickBlock', 'quickCreate'])
const dados_de_exemplo = {
totalSessions: 6,
totalMinutes: 300,
biggestFreeWindow: '2h 10m',
pending: 0,
reschedules: 1,
attentions: 1,
suggested1: '14:00',
suggested2: '16:30',
nextBreak: '12:00'
}
const s = computed(() => {
const base = props.stats && Object.keys(props.stats).length ? props.stats : dados_de_exemplo
return {
totalSessions: base.totalSessions ?? 0,
totalMinutes: base.totalMinutes ?? 0,
biggestFreeWindow: base.biggestFreeWindow ?? '—',
pending: base.pending ?? 0,
reschedules: base.reschedules ?? 0,
attentions: base.attentions ?? 0,
suggested1: base.suggested1 ?? '—',
suggested2: base.suggested2 ?? '—',
nextBreak: base.nextBreak ?? '—'
}
})
function minutesToHuman(min) {
const n = Number(min || 0)
const h = Math.floor(n / 60)
const m = n % 60
if (h <= 0) return `${m}m`
if (m <= 0) return `${h}h`
return `${h}h ${m}m`
}
const totalTimeHuman = computed(() => minutesToHuman(s.value.totalMinutes))
const attentionSeverity = computed(() => {
if (s.value.attentions >= 3) return 'danger'
if (s.value.attentions >= 1) return 'warning'
return 'success'
})
</script>
<template>
<Card>
<template #title>
<div class="flex align-items-center justify-content-between gap-2 flex-wrap">
<div class="flex flex-column">
<span>Pulso da agenda</span>
<span class="text-xs" style="color: var(--text-color-secondary);">
Indicadores rápidos para decisão imediata.
</span>
</div>
<div class="flex align-items-center gap-2">
<Tag :severity="attentionSeverity" :value="`Atenções: ${s.attentions}`" />
</div>
</div>
</template>
<template #content>
<div class="grid gap-2">
<!-- Linha 1: métricas -->
<div class="grid gap-2" style="grid-template-columns: 1fr 1fr;">
<div class="p-3 border-round-xl" style="border: 1px solid var(--surface-border); background: var(--surface-card);">
<div class="text-xs" style="color: var(--text-color-secondary);">Sessões (no filtro)</div>
<div class="text-xl font-semibold mt-1">{{ s.totalSessions }}</div>
</div>
<div class="p-3 border-round-xl" style="border: 1px solid var(--surface-border); background: var(--surface-card);">
<div class="text-xs" style="color: var(--text-color-secondary);">Tempo total</div>
<div class="text-xl font-semibold mt-1">{{ totalTimeHuman }}</div>
</div>
</div>
<!-- Linha 2: janelas e atenção -->
<div class="grid gap-2" style="grid-template-columns: 1fr 1fr;">
<div class="p-3 border-round-xl" style="border: 1px solid var(--surface-border); background: var(--surface-card);">
<div class="text-xs" style="color: var(--text-color-secondary);">Maior janela livre</div>
<div class="text-base font-semibold mt-1">{{ s.biggestFreeWindow }}</div>
<div class="text-xs mt-2" style="color: var(--text-color-secondary);">
Sugestões: <b>{{ s.suggested1 }}</b> e <b>{{ s.suggested2 }}</b>
</div>
</div>
<div class="p-3 border-round-xl" style="border: 1px solid var(--surface-border); background: var(--surface-card);">
<div class="text-xs" style="color: var(--text-color-secondary);">Pontos de atenção</div>
<div class="flex align-items-center gap-2 mt-2 flex-wrap">
<Tag severity="warning" :value="`Pendências: ${s.pending}`" />
<Tag severity="info" :value="`Remarcar: ${s.reschedules}`" />
</div>
<div class="text-xs mt-2" style="color: var(--text-color-secondary);">
Próxima pausa: <b>{{ s.nextBreak }}</b>
</div>
</div>
</div>
<Divider class="my-2" />
<!-- Ações rápidas -->
<div class="flex align-items-center justify-content-between gap-2 flex-wrap">
<div class="text-xs" style="color: var(--text-color-secondary);">
Ações rápidas (criação sempre abre modal nada nasce direto).
</div>
<div class="flex align-items-center gap-2">
<Button
size="small"
icon="pi pi-plus"
label="Nova sessão"
@click="emit('quickCreate')"
/>
<Button
size="small"
icon="pi pi-lock"
severity="secondary"
label="Bloquear horário"
@click="emit('quickBlock')"
/>
</div>
</div>
</div>
</template>
</Card>
</template>