Skip to content

Dashboard

Visão Geral

A Dashboard (/dashboard) consolida KPIs de membros, finanças, minhas escalas e aniversariantes. Renderizada por DashboardController@indexresources/js/pages/Dashboard.vue.

Gate por Permissão (Opção B)

Cada widget é condicionado a uma permissão Spatie. Usuários recém-cadastrados (sem role atribuída) veem apenas um estado de boas-vindas. Isto é importante porque o auto-cadastro não atribui papéis — os administradores definem a função depois.

WidgetPermissãoFonte dos dados
Membros ativos, Membros por situação, Aniversariantes da semanamember.viewMember::count, query agrupada, GetBirthdayMembersAction
Receitas/Despesas/Saldo/Dízimos, Chart Receitas vs Despesas, Top 5 Despesasfinance.viewTransaction
Minhas Escalaspróprio membroScheduleItem filtrado por member_id do usuário logado
Engajamentofeature member_insights_basic + permission member_insights.view_fullMemberEngagementScore

Estratégia

  1. DashboardController@index calcula $canViewMembers/$canViewFinance via $user->can('...').
  2. Só executa as queries quando a permissão existe — economiza DB round-trips e evita leaks de dados agregados.
  3. Passa flags (canViewMembers, canViewFinance) para o Inertia + props na view.
  4. Dashboard.vue usa v-if="canViewMembers" e v-if="canViewFinance" em cada bloco.
  5. Se usuário não tem nenhuma permissão, nenhum schedule e nenhum engagementWidget, exibe card "Bem-vindo(a) — aguarde sua função ser atribuída".

Avatar no widget de aniversariantes

DashboardController envia avatar_url do membro via getFirstMediaUrl('foto') (collection foto, não avatar). Ver Módulo Membros.

Arquivos

  • app/Http/Controllers/DashboardController.php
  • resources/js/pages/Dashboard.vue

Estender

Para adicionar um novo widget gated:

  1. Definir/reutilizar a permissão em database/seeders/Production/RoleAndPermissionSeeder.php.
  2. No controller, guardar o cálculo dentro de if ($user?->can('nova.permission')) { ... }.
  3. Passar a flag no Inertia::render.
  4. Na view: <div v-if="canNovaPermissao">...</div>.
  5. Incluir a nova permissão no hasAnyWidget computed para o empty state não aparecer indevidamente.