Redesenha top clientes por horas
This commit is contained in:
parent
34018bed04
commit
25321224a6
1 changed files with 37 additions and 16 deletions
|
|
@ -15,8 +15,9 @@ import { Input } from "@/components/ui/input"
|
||||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
|
||||||
import { usePersistentCompanyFilter } from "@/lib/use-company-filter"
|
import { usePersistentCompanyFilter } from "@/lib/use-company-filter"
|
||||||
import { Progress } from "@/components/ui/progress"
|
import { Progress } from "@/components/ui/progress"
|
||||||
import { Bar, BarChart, CartesianGrid, XAxis } from "recharts"
|
import { Bar, BarChart, CartesianGrid, XAxis, YAxis } from "recharts"
|
||||||
import { ChartContainer, ChartTooltip, ChartTooltipContent } from "@/components/ui/chart"
|
import { ChartContainer, ChartLegend, ChartLegendContent, ChartTooltip, ChartTooltipContent } from "@/components/ui/chart"
|
||||||
|
import type { ChartConfig } from "@/components/ui/chart"
|
||||||
import { formatHoursCompact } from "@/lib/utils"
|
import { formatHoursCompact } from "@/lib/utils"
|
||||||
|
|
||||||
type HoursItem = {
|
type HoursItem = {
|
||||||
|
|
@ -32,11 +33,13 @@ type HoursItem = {
|
||||||
const topClientsChartConfig = {
|
const topClientsChartConfig = {
|
||||||
internas: {
|
internas: {
|
||||||
label: "Horas internas",
|
label: "Horas internas",
|
||||||
|
color: "var(--chart-1)",
|
||||||
},
|
},
|
||||||
externas: {
|
externas: {
|
||||||
label: "Horas externas",
|
label: "Horas externas",
|
||||||
|
color: "var(--chart-2)",
|
||||||
},
|
},
|
||||||
}
|
} satisfies ChartConfig
|
||||||
|
|
||||||
export function HoursReport() {
|
export function HoursReport() {
|
||||||
const [timeRange, setTimeRange] = useState("90d")
|
const [timeRange, setTimeRange] = useState("90d")
|
||||||
|
|
@ -95,6 +98,19 @@ export function HoursReport() {
|
||||||
}),
|
}),
|
||||||
[filtered]
|
[filtered]
|
||||||
)
|
)
|
||||||
|
const topClientsData = useMemo(
|
||||||
|
() =>
|
||||||
|
filteredWithComputed
|
||||||
|
.slice()
|
||||||
|
.sort((a, b) => b.total - a.total)
|
||||||
|
.slice(0, 10)
|
||||||
|
.map((row) => ({
|
||||||
|
name: row.name,
|
||||||
|
internas: row.internal,
|
||||||
|
externas: row.external,
|
||||||
|
})),
|
||||||
|
[filteredWithComputed]
|
||||||
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
|
|
@ -107,24 +123,26 @@ export function HoursReport() {
|
||||||
{!filteredWithComputed || filteredWithComputed.length === 0 ? (
|
{!filteredWithComputed || filteredWithComputed.length === 0 ? (
|
||||||
<p className="rounded-lg border border-dashed border-slate-200 p-6 text-sm text-neutral-500">Sem dados para o período.</p>
|
<p className="rounded-lg border border-dashed border-slate-200 p-6 text-sm text-neutral-500">Sem dados para o período.</p>
|
||||||
) : (
|
) : (
|
||||||
<ChartContainer config={topClientsChartConfig} className="aspect-auto h-[260px] w-full">
|
<ChartContainer config={topClientsChartConfig} className="aspect-auto h-[320px] w-full">
|
||||||
<BarChart
|
<BarChart
|
||||||
data={filteredWithComputed
|
data={topClientsData}
|
||||||
.slice()
|
layout="vertical"
|
||||||
.sort((a, b) => b.total - a.total)
|
margin={{ top: 16, right: 24, bottom: 16, left: 0 }}
|
||||||
.slice(0, 10)
|
barCategoryGap={12}
|
||||||
.map((r) => ({ name: r.name, internas: r.internal, externas: r.external }))}
|
|
||||||
margin={{ top: 8, left: 20, right: 20, bottom: 56 }}
|
|
||||||
barCategoryGap={32}
|
|
||||||
>
|
>
|
||||||
<CartesianGrid vertical={false} />
|
<CartesianGrid horizontal vertical={false} />
|
||||||
<XAxis dataKey="name" tickLine={false} axisLine={false} tickMargin={24} interval={0} angle={-30} height={80} />
|
<XAxis
|
||||||
<Bar dataKey="internas" stackId="a" fill="var(--chart-1)" radius={[4, 4, 0, 0]} barSize={28} />
|
type="number"
|
||||||
<Bar dataKey="externas" stackId="a" fill="var(--chart-2)" radius={[4, 4, 0, 0]} barSize={28} />
|
tickLine={false}
|
||||||
|
axisLine={false}
|
||||||
|
tickFormatter={(value) => formatHoursCompact(Number(value))}
|
||||||
|
/>
|
||||||
|
<YAxis dataKey="name" type="category" tickLine={false} axisLine={false} width={180} />
|
||||||
<ChartTooltip
|
<ChartTooltip
|
||||||
content={
|
content={
|
||||||
<ChartTooltipContent
|
<ChartTooltipContent
|
||||||
className="w-[200px]"
|
className="w-[220px]"
|
||||||
|
labelFormatter={(value) => <span className="font-semibold text-foreground">{String(value)}</span>}
|
||||||
formatter={(value, name) => (
|
formatter={(value, name) => (
|
||||||
<>
|
<>
|
||||||
<span className="text-muted-foreground">
|
<span className="text-muted-foreground">
|
||||||
|
|
@ -136,6 +154,9 @@ export function HoursReport() {
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
<ChartLegend content={<ChartLegendContent />} />
|
||||||
|
<Bar dataKey="internas" stackId="hours" fill="var(--color-internas)" radius={[8, 0, 0, 8]} barSize={18} />
|
||||||
|
<Bar dataKey="externas" stackId="hours" fill="var(--color-externas)" radius={[0, 8, 8, 0]} barSize={18} />
|
||||||
</BarChart>
|
</BarChart>
|
||||||
</ChartContainer>
|
</ChartContainer>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue