feat: enhance tickets portal and admin flows
This commit is contained in:
parent
9cdd8763b4
commit
c15f0a5b09
67 changed files with 1101 additions and 338 deletions
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue