feat(reports): simplify dashboards, align OT flow labels, and normalize filters
This commit is contained in:
@@ -4,17 +4,9 @@ import { useQueries, useQuery } from '@tanstack/react-query'
|
||||
import { useTheme } from '@/hooks/useTheme'
|
||||
import { apiFetch } from '@/lib/api'
|
||||
import type { Client, Expense, Invoice, Staff, WorkOrder, WorkOrderDetail } from '@/lib/types'
|
||||
import { WORK_ORDER_STATUS_LABEL } from '@/lib/workOrderStatus'
|
||||
|
||||
const STATUS_LABEL: Record<WorkOrder['status'], string> = {
|
||||
quote: 'Orçamento',
|
||||
open: 'Orçamento Aprovado',
|
||||
in_progress: 'Em Curso',
|
||||
completed: 'Concluída',
|
||||
invoiced: 'Faturada',
|
||||
cancelled: 'Cancelada',
|
||||
}
|
||||
|
||||
const STATUS_ORDER: WorkOrder['status'][] = ['quote', 'open', 'in_progress', 'completed', 'invoiced', 'cancelled']
|
||||
const STATUS_ORDER: WorkOrder['status'][] = ['quote', 'in_progress', 'completed', 'invoiced', 'cancelled']
|
||||
type PeriodKey = 'month' | '30d' | '90d' | 'year'
|
||||
|
||||
const PERIOD_OPTIONS: { key: PeriodKey; label: string }[] = [
|
||||
@@ -149,7 +141,8 @@ export default function DashboardPage() {
|
||||
const byStatus = Object.fromEntries(STATUS_ORDER.map((s) => [s, 0])) as Record<WorkOrder['status'], number>
|
||||
for (const wo of workOrdersPeriod) byStatus[wo.status] += 1
|
||||
|
||||
const activeOrders = byStatus.quote + byStatus.open + byStatus.in_progress
|
||||
const activeOrders = byStatus.quote + byStatus.in_progress
|
||||
const awaitingInvoice = workOrdersPeriod.filter((wo) => wo.status === 'completed').length
|
||||
const periodExpenses = expensesPeriod.reduce((sum, e) => sum + e.amount, 0)
|
||||
const monthExpenses = expensesMonth.reduce((sum, e) => sum + e.amount, 0)
|
||||
const monthDocs = invoicesMonth.length
|
||||
@@ -172,6 +165,7 @@ export default function DashboardPage() {
|
||||
return {
|
||||
byStatus,
|
||||
activeOrders,
|
||||
awaitingInvoice,
|
||||
periodExpenses,
|
||||
periodEntries,
|
||||
monthEntries,
|
||||
@@ -236,7 +230,7 @@ export default function DashboardPage() {
|
||||
|
||||
<div className="grid gap-3 md:grid-cols-2 xl:grid-cols-4">
|
||||
<DashboardCard
|
||||
title="OTs Ativas"
|
||||
title="Orçamento + Iniciar Trabalho"
|
||||
value={String(metrics.activeOrders)}
|
||||
subtitle={`No período (${metrics.periodOrdersCount} OTs)`}
|
||||
isLight={isLight}
|
||||
@@ -326,7 +320,7 @@ export default function DashboardPage() {
|
||||
return (
|
||||
<div key={status}>
|
||||
<div className="mb-1 flex justify-between text-xs">
|
||||
<span className={isLight ? 'text-slate-700' : 'text-slate-300'}>{STATUS_LABEL[status]}</span>
|
||||
<span className={isLight ? 'text-slate-700' : 'text-slate-300'}>{WORK_ORDER_STATUS_LABEL[status]}</span>
|
||||
<span className={`font-mono ${isLight ? 'text-slate-500' : 'text-slate-400'}`}>{count}</span>
|
||||
</div>
|
||||
<div className={`h-2 rounded-full ${isLight ? 'bg-slate-200' : 'bg-slate-800'}`}>
|
||||
@@ -355,16 +349,16 @@ export default function DashboardPage() {
|
||||
>
|
||||
<p className="text-xs uppercase tracking-wide">Ação recomendada</p>
|
||||
<p className="mt-1">
|
||||
{metrics.byStatus.completed > 0
|
||||
? `${metrics.byStatus.completed} OT(s) concluída(s) pronta(s) para faturar.`
|
||||
: 'Sem OTs concluídas pendentes de faturação.'}
|
||||
{metrics.awaitingInvoice > 0
|
||||
? `${metrics.awaitingInvoice} OT(s) em "Concluir OT" pronta(s) para faturar.`
|
||||
: 'Sem OTs finalizadas pendentes de emissão de fatura.'}
|
||||
</p>
|
||||
</div>
|
||||
<div className={`rounded-lg border px-3 py-2 ${isLight ? 'border-cyan-200 bg-cyan-50 text-cyan-900' : 'border-cyan-900/70 bg-cyan-950/25 text-cyan-100'}`}>
|
||||
<p className="text-xs uppercase tracking-wide">Em orçamento</p>
|
||||
<p className="mt-1">
|
||||
{metrics.byStatus.quote > 0
|
||||
? `${metrics.byStatus.quote} OT(s) em orçamento aguardam aprovação.`
|
||||
? `${metrics.byStatus.quote} OT(s) em "Orçamento" prontas para "Iniciar Trabalho".`
|
||||
: 'Não existem OTs pendentes em orçamento.'}
|
||||
</p>
|
||||
</div>
|
||||
@@ -394,7 +388,7 @@ export default function DashboardPage() {
|
||||
<li key={wo.id} className="flex items-center justify-between py-2">
|
||||
<div>
|
||||
<p className={`text-sm font-medium ${isLight ? 'text-slate-900' : 'text-white'}`}>OT #{wo.number}</p>
|
||||
<p className={`text-xs ${isLight ? 'text-slate-600' : 'text-slate-400'}`}>{STATUS_LABEL[wo.status]}</p>
|
||||
<p className={`text-xs ${isLight ? 'text-slate-600' : 'text-slate-400'}`}>{WORK_ORDER_STATUS_LABEL[wo.status]}</p>
|
||||
</div>
|
||||
<span className={`text-xs ${isLight ? 'text-slate-500' : 'text-slate-500'}`}>
|
||||
{new Intl.DateTimeFormat('pt-PT', { dateStyle: 'short', timeStyle: 'short' }).format(new Date(wo.updated_at))}
|
||||
|
||||
Reference in New Issue
Block a user