"use client" import * as React from "react" import { Area, AreaChart, CartesianGrid, XAxis } from "recharts" 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 { useIsMobile } from "@/hooks/use-mobile" import { Card, CardAction, CardContent, CardDescription, CardHeader, CardTitle, } from "@/components/ui/card" import { Button } from "@/components/ui/button" import { ChartConfig, ChartContainer, ChartTooltip, ChartTooltipContent, } from "@/components/ui/chart" import { formatDateDM, formatDateDMY } from "@/lib/utils" import { Skeleton } from "@/components/ui/skeleton" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select" import { Input } from "@/components/ui/input" import { usePersistentCompanyFilter } from "@/lib/use-company-filter" import { ToggleGroup, ToggleGroupItem, } from "@/components/ui/toggle-group" export const description = "Distribuição semanal de tickets por canal" export function ChartAreaInteractive() { const [mounted, setMounted] = React.useState(false) const isMobile = useIsMobile() const [timeRange, setTimeRange] = React.useState("7d") // Persistir seleção de empresa globalmente const [companyId, setCompanyId] = usePersistentCompanyFilter("all") const [companyQuery, setCompanyQuery] = React.useState("") const { session, convexUserId, isStaff } = useAuth() const tenantId = session?.user.tenantId ?? DEFAULT_TENANT_ID React.useEffect(() => { setMounted(true) }, []) React.useEffect(() => { if (isMobile) { setTimeRange("7d") } }, [isMobile]) const reportsEnabled = Boolean(isStaff && convexUserId) const report = useQuery( api.reports.ticketsByChannel, reportsEnabled ? ({ tenantId, viewerId: convexUserId as Id<"users">, range: timeRange, companyId: companyId === "all" ? undefined : (companyId as Id<"companies">) }) : "skip" ) const companies = useQuery( api.companies.list, reportsEnabled ? { tenantId, viewerId: convexUserId as Id<"users"> } : "skip" ) as Array<{ id: Id<"companies">; name: string }> | undefined const filteredCompanies = React.useMemo(() => { const q = companyQuery.trim().toLowerCase() if (!q) return companies ?? [] return (companies ?? []).filter((c) => c.name.toLowerCase().includes(q)) }, [companies, companyQuery]) const channels = React.useMemo(() => report?.channels ?? [], [report]) const palette = React.useMemo( () => [ "var(--chart-1)", "var(--chart-2)", "var(--chart-3)", "var(--chart-4)", "var(--chart-5)", ], [] ) const chartConfig = React.useMemo(() => { const entries = channels.map((channel: string, index: number) => [ channel, { label: channel .toLowerCase() .replace(/_/g, " ") .replace(/\b\w/g, (letter) => letter.toUpperCase()), color: palette[index % palette.length], }, ]) return Object.fromEntries(entries) as ChartConfig }, [channels, palette]) const chartData = React.useMemo(() => { if (!report?.points) return [] return report.points.map((point: { date: string; values: Record }) => { const entry: Record = { date: point.date } for (const channel of channels) { entry[channel] = point.values[channel] ?? 0 } return entry }) }, [channels, report]) if (!mounted) { return (
Carregando gráfico...
) } return ( Entrada de tickets por canal Distribuição dos canais nos últimos {timeRange.replace("d", " dias")} Período: {timeRange}
{/* Company picker with search */} setCompanyQuery(e.target.value)} className="h-8" />
Todas as empresas {filteredCompanies.map((c) => ( {c.name} ))} {/* Desktop time range toggles */} 90 dias 30 dias 7 dias {/* Mobile time range select */} {/* Export button aligned at the end */}
{report === undefined ? (
) : chartData.length === 0 || channels.length === 0 ? (
Sem dados suficientes no período selecionado.
) : ( {channels.map((channel: string) => ( ))} formatDateDM(new Date(value))} /> formatDateDMY(new Date(value as string))} indicator="dot" /> } /> {channels .slice() .reverse() .map((channel: string) => ( ))} )}
) } export default ChartAreaInteractive