"use client" import { useState, useMemo } from "react" import { useQuery } from "convex/react" import { api } from "@/convex/_generated/api" import type { Id } from "@/convex/_generated/dataModel" import { useAuth } from "@/lib/auth-client" import { DEFAULT_TENANT_ID } from "@/lib/constants" import { Card, CardAction, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" import { Badge } from "@/components/ui/badge" import { Button } from "@/components/ui/button" import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group" import { Input } from "@/components/ui/input" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select" import { usePersistentCompanyFilter } from "@/lib/use-company-filter" import { Progress } from "@/components/ui/progress" import { Bar, BarChart, CartesianGrid, XAxis } from "recharts" import { ChartContainer, ChartTooltip, ChartTooltipContent } from "@/components/ui/chart" type HoursItem = { companyId: string name: string isAvulso: boolean internalMs: number externalMs: number totalMs: number contractedHoursPerMonth?: number | null } export function HoursReport() { const [timeRange, setTimeRange] = useState("90d") const [query, setQuery] = useState("") const [companyId, setCompanyId] = usePersistentCompanyFilter("all") const { session, convexUserId, isStaff } = useAuth() const tenantId = session?.user.tenantId ?? DEFAULT_TENANT_ID const enabled = Boolean(isStaff && convexUserId) const data = useQuery( api.reports.hoursByClient, enabled ? { tenantId, viewerId: convexUserId as Id<"users">, range: timeRange } : "skip" ) as { rangeDays: number; items: HoursItem[] } | undefined const companies = useQuery(api.companies.list, enabled ? { tenantId, viewerId: convexUserId as Id<"users"> } : "skip") as Array<{ id: Id<"companies">; name: string }> | undefined const filtered = useMemo(() => { const items = data?.items ?? [] const q = query.trim().toLowerCase() let list = items if (companyId !== "all") list = list.filter((it) => String(it.companyId) === companyId) if (q) list = list.filter((it) => it.name.toLowerCase().includes(q)) return list }, [data?.items, query, companyId]) const totals = useMemo(() => { return filtered.reduce( (acc, item) => { acc.internal += item.internalMs / 3600000 acc.external += item.externalMs / 3600000 acc.total += item.totalMs / 3600000 return acc }, { internal: 0, external: 0, total: 0 } ) }, [filtered]) const numberFormatter = useMemo( () => new Intl.NumberFormat("pt-BR", { minimumFractionDigits: 2, maximumFractionDigits: 2, }), [] ) const filteredWithComputed = useMemo( () => filtered.map((row) => { const internal = row.internalMs / 3600000 const external = row.externalMs / 3600000 const total = row.totalMs / 3600000 const contracted = row.contractedHoursPerMonth ?? null const usagePercent = contracted && contracted > 0 ? Math.min(100, Math.round((total / contracted) * 100)) : null return { ...row, internal, external, total, contracted, usagePercent, } }), [filtered] ) return (
Sem dados para o período.
) : ({item.label}
{item.value} h
ID {row.companyId}