Skip to content

Monitoring Module - Monitoramento de Horas

Módulo para acompanhamento de horas trabalhadas pelos prestadores (providers). O borrower (contratante) acompanha as horas que os providers (prestadores) lançam na plataforma.


Visão Geral

O módulo permite:

  • Listar prestadores com resumo de horas (semanal/mensal)
  • Visualizar detalhes de horas por prestador
  • Visualizar entradas diárias de trabalho
  • Criar/editar/excluir entradas de trabalho
  • Gerar relatórios de horas

Estrutura do Módulo

src/modules/monitoring/
├── pages/
│   ├── index.vue                 # Página raiz (redirect)
│   ├── ListMonitoring.vue        # Lista de prestadores
│   ├── MonitoringDetail.vue      # Detalhes de um prestador
│   └── ListReport.vue            # Relatórios (em desenvolvimento)
├── components/
│   ├── List/
│   │   ├── MonitoringTableList.vue   # Tabela de prestadores
│   │   ├── MonitoringFilters.vue     # Filtro por status
│   │   ├── TableHeader.vue           # Cabeçalho com busca
│   │   └── ExportListModal.vue       # Modal para exportar lista
│   └── Detail/
│       ├── DetailHeader.vue          # Cabeçalho do detalhe
│       ├── SummaryCard.vue           # Card de resumo
│       ├── WeeklySummary.vue         # Gráfico semanal
│       ├── MonthlySummary.vue        # Gráfico mensal
│       ├── DailyEntriesFlat.vue      # Lista de entradas diárias
│       ├── ConsolidatedTable.vue     # Tabela consolidada
│       ├── WorkEntryModal.vue        # Modal CRUD de entradas
│       └── ExportReportModal.vue     # Modal para exportar relatório
├── services/
│   └── monitoring.ts             # Chamadas de API
├── stores/
│   └── monitoring.ts             # Pinia store
└── router/
    └── index.ts                  # Rotas do módulo

API Endpoints

Providers (Monitoring)

MétodoEndpointDescrição
GET/monitoring/Lista providers com resumo de horas
GET/monitoring/:idDetalhes de um provider (com summaries)
GET/monitoring/:id/entriesLista entradas de trabalho

Work Entries

MétodoEndpointDescrição
GET/monitoring/entries/:idBusca entrada específica
POST/monitoring/entriesCria nova entrada
PUT/monitoring/entries/:idAtualiza entrada
DELETE/monitoring/entries/:idRemove entrada

Query Parameters

GET /monitoring/

?search=string      # Busca por nome da empresa ou contrato
&status=string      # 'active' | 'inactive' | 'all'

GET /monitoring/:id/entries

?startDate=string   # Data inicial (ISO date)
&endDate=string     # Data final (ISO date)

Tipos (Domain)

ProviderWithHours

typescript
interface ProviderWithHours {
  id: string // UUID
  companyId: string
  companyName: string
  contractId: string
  contractName: string
  totalHoursMonth: number
  totalHoursWeek: number
  lastEntry?: Date
  status: 'active' | 'inactive'
}

ProviderHoursDetail

Retornado pelo endpoint GET /monitoring/:id:

typescript
interface ProviderHoursDetail {
  provider: ProviderWithHours
  dailySummary: DailySummary[]
  weeklySummary: WeeklySummary
  monthlySummary: MonthlySummary
}

WorkEntry

typescript
interface WorkEntry {
  id: string // UUID
  providerId: string // UUID do provider
  date: Date
  startTime: string // Formato "HH:mm"
  endTime: string // Formato "HH:mm"
  totalMinutes: number
  description: string
  reason?: string // Motivo (para exclusões)
  tasks: WorkTask[]
  createdAt: Date
  updatedAt: Date
}

interface WorkTask {
  id: string
  description: string
  durationMinutes: number
}

Summaries

typescript
interface DailySummary {
  date: Date
  totalMinutes: number
  entries: WorkEntry[]
}

interface WeeklySummary {
  weekStart: Date
  weekEnd: Date
  totalMinutes: number
  dailyTotals: { date: Date; minutes: number }[]
}

interface MonthlySummary {
  month: number // 1-12
  year: number
  totalMinutes: number
  weeklyTotals: { weekNumber: number; minutes: number }[]
}

Payloads

typescript
// POST /monitoring/entries - Criar nova entrada
interface CreateWorkEntryPayload {
  providerId: string // Obrigatório no POST
  date: Date
  startTime: string // Formato "HH:mm"
  endTime: string // Formato "HH:mm"
  description: string
  reason?: string
  tasks: { description: string; durationMinutes: number }[]
}

// PUT /monitoring/entries/:id - Atualizar entrada existente
// Nota: providerId NÃO é enviado no PUT (já está associado à entry)
interface UpdateWorkEntryPayload {
  date?: Date
  startTime?: string // Formato "HH:mm"
  endTime?: string // Formato "HH:mm"
  description?: string
  reason?: string
  tasks?: { description: string; durationMinutes: number }[]
}

interface MonitoringFilter {
  search?: string
  status?: 'active' | 'inactive' | 'all'
}

interface WorkEntryFilter {
  providerId?: string
  startDate?: Date
  endDate?: Date
}

Store (Pinia)

Estado

typescript
{
  items: ProviderWithHours[]          // Lista de prestadores
  total: number                       // Total de prestadores
  search: string                      // Valor de busca
  status: 'active' | 'inactive' | 'all'  // Filtro de status
  selectedIds: string[]               // IDs selecionados
  currentProvider: ProviderHoursDetail | null  // Prestador atual
  entries: WorkEntry[]                // Entradas do prestador atual
  entriesTotal: number                // Total de entradas
  loadingDetail: boolean              // Flag de carregamento
  initialized: boolean                // Flag de inicialização
  loading: boolean                    // Flag de carregamento da lista
}

Ações

AçãoDescrição
loadProviders(params?)Carrega lista de prestadores
setSearch(params)Define filtros e recarrega
loadProviderDetail(id)Carrega detalhes de um prestador
loadProviderEntries(id, params?)Carrega entradas de um prestador
deleteEntry(id)Deleta uma entrada
setSelectedIds(ids)Define IDs selecionados
clearSelection()Limpa seleção
reset()Reseta filtros
resetDetail()Reseta detalhes do prestador atual

Services

typescript
// Lista prestadores com horas
getProvidersWithHoursService(params?: ProvidersFilter)
  => GET /monitoring/

// Detalhes de um prestador
getProviderDetailService(id: string)
  => GET /monitoring/:id

// Entradas de um prestador
getProviderEntriesService(id: string, params?: EntriesFilter)
  => GET /monitoring/:id/entries

// Busca entrada específica
getWorkEntryService(id: string)
  => GET /monitoring/entries/:id

// Cria entrada
createWorkEntryService(data: CreateWorkEntryPayload)
  => POST /monitoring/entries

// Atualiza entrada
updateWorkEntryService(id: string, data: Partial<CreateWorkEntryPayload>)
  => PUT /monitoring/entries/:id

// Remove entrada
deleteWorkEntryService(id: string)
  => DELETE /monitoring/entries/:id

Rotas

PathNomeComponenteDescrição
/monitoringmonitoring-listListMonitoring.vueLista de prestadores
/monitoring/:idmonitoring-detailMonitoringDetail.vueDetalhes do prestador

Fluxo de Dados

Backend API

services/monitoring.ts (HTTP calls)

stores/monitoring.ts (Pinia Store)

Componentes Vue
    ├── ListMonitoring (lê items, loading)
    ├── MonitoringDetail (lê currentProvider, entries)
    └── WorkEntryModal (create/update entries)

Respostas da API

GET /monitoring/

json
{
  "data": [
    {
      "id": "uuid",
      "companyId": "uuid",
      "companyName": "Tech Solutions Ltda",
      "contractId": "uuid",
      "contractName": "Contrato de Prestação de Serviços",
      "totalHoursMonth": 168,
      "totalHoursWeek": 42,
      "lastEntry": "2026-01-26T10:00:00Z",
      "status": "active"
    }
  ],
  "total": 1
}

GET /monitoring/:id

json
{
  "provider": { ... },
  "dailySummary": [
    {
      "date": "2026-01-26T00:00:00Z",
      "totalMinutes": 480,
      "entries": [ ... ]
    }
  ],
  "weeklySummary": {
    "weekStart": "2026-01-20T00:00:00Z",
    "weekEnd": "2026-01-26T00:00:00Z",
    "totalMinutes": 2400,
    "dailyTotals": [
      { "date": "2026-01-20T00:00:00Z", "minutes": 480 },
      ...
    ]
  },
  "monthlySummary": {
    "month": 1,
    "year": 2026,
    "totalMinutes": 10080,
    "weeklyTotals": [
      { "weekNumber": 1, "minutes": 2400 },
      ...
    ]
  }
}

GET /monitoring/:id/entries

json
{
  "data": [
    {
      "id": "uuid",
      "providerId": "uuid",
      "date": "2026-01-26T00:00:00Z",
      "startTime": "08:00",
      "endTime": "12:00",
      "totalMinutes": 240,
      "description": "Desenvolvimento de funcionalidades",
      "tasks": [
        {
          "id": "uuid",
          "description": "Implementação da listagem",
          "durationMinutes": 90
        }
      ],
      "createdAt": "2026-01-26T08:00:00Z",
      "updatedAt": "2026-01-26T08:00:00Z"
    }
  ],
  "total": 1
}

POST /monitoring/entries

Request:

json
{
  "providerId": "uuid",
  "date": "2026-01-26T00:00:00Z",
  "startTime": "08:00",
  "endTime": "12:00",
  "description": "Desenvolvimento de funcionalidades",
  "tasks": [{ "description": "Implementação", "durationMinutes": 90 }]
}

Response: WorkEntry criada (status 201)


Integração com Provider Module

O módulo provider também utiliza o store de monitoring para que prestadores lancem suas próprias horas:

  • LogHoursEntryPage.vue - Página para prestador lançar horas
  • LogHoursHeader.vue - Cabeçalho com informações do prestador

Esses componentes usam as mesmas actions do store (loadProviderDetail, loadProviderEntries).