feat: enhance tickets portal and admin flows

This commit is contained in:
Esdras Renan 2025-10-07 02:26:09 -03:00
parent 9cdd8763b4
commit c15f0a5b09
67 changed files with 1101 additions and 338 deletions

View file

@ -4,7 +4,6 @@ import * as React from "react"
import { Area, AreaChart, CartesianGrid, XAxis } from "recharts"
import { useQuery } from "convex/react"
// @ts-expect-error Convex runtime API lacks TypeScript declarations
import { api } from "@/convex/_generated/api"
import type { Id } from "@/convex/_generated/dataModel"
import { useAuth } from "@/lib/auth-client"
@ -39,17 +38,22 @@ import {
export const description = "Distribuição semanal de tickets por canal"
export function ChartAreaInteractive() {
const isMobile = useIsMobile()
export function ChartAreaInteractive() {
const [mounted, setMounted] = React.useState(false)
const isMobile = useIsMobile()
const [timeRange, setTimeRange] = React.useState("7d")
const { session, convexUserId } = useAuth()
const tenantId = session?.user.tenantId ?? DEFAULT_TENANT_ID
React.useEffect(() => {
if (isMobile) {
setTimeRange("7d")
}
}, [isMobile])
React.useEffect(() => {
setMounted(true)
}, [])
React.useEffect(() => {
if (isMobile) {
setTimeRange("7d")
}
}, [isMobile])
const report = useQuery(
api.reports.ticketsByChannel,
@ -72,7 +76,7 @@ export function ChartAreaInteractive() {
)
const chartConfig = React.useMemo(() => {
const entries = channels.map((channel, index) => [
const entries = channels.map((channel: string, index: number) => [
channel,
{
label: channel
@ -87,7 +91,7 @@ export function ChartAreaInteractive() {
const chartData = React.useMemo(() => {
if (!report?.points) return []
return report.points.map((point) => {
return report.points.map((point: { date: string; values: Record<string, number> }) => {
const entry: Record<string, number | string> = { date: point.date }
for (const channel of channels) {
entry[channel] = point.values[channel] ?? 0
@ -95,6 +99,14 @@ export function ChartAreaInteractive() {
return entry
})
}, [channels, report])
if (!mounted) {
return (
<div className="flex h-[250px] items-center justify-center rounded-xl border border-dashed border-border/60 text-sm text-muted-foreground">
Carregando gráfico...
</div>
)
}
return (
<Card className="@container/card">
@ -156,7 +168,7 @@ export function ChartAreaInteractive() {
>
<AreaChart data={chartData}>
<defs>
{channels.map((channel) => (
{channels.map((channel: string) => (
<linearGradient key={channel} id={`fill-${channel}`} x1="0" y1="0" x2="0" y2="1">
<stop
offset="5%"
@ -203,7 +215,7 @@ export function ChartAreaInteractive() {
{channels
.slice()
.reverse()
.map((channel) => (
.map((channel: string) => (
<Area
key={channel}
dataKey={channel}
@ -212,7 +224,11 @@ export function ChartAreaInteractive() {
stroke={chartConfig[channel]?.color ?? "var(--chart-1)"}
strokeWidth={2}
stackId="a"
name={chartConfig[channel]?.label ?? channel}
name={
typeof chartConfig[channel]?.label === "string"
? (chartConfig[channel]?.label as string)
: channel
}
/>
))}
</AreaChart>
@ -221,4 +237,6 @@ export function ChartAreaInteractive() {
</CardContent>
</Card>
)
}
}
export default ChartAreaInteractive