11"use client" ;
22
33import { useState } from "react" ;
4- import {
5- AreaChart ,
6- Area ,
7- XAxis ,
8- YAxis ,
9- CartesianGrid ,
10- Tooltip ,
11- ResponsiveContainer ,
12- } from "recharts" ;
4+ import { AreaChart , ChartCard , ChartTooltip } from "@/components/ui/charts" ;
135import { formatCurrency } from "@/lib/utils" ;
146
157interface DailyActivity {
@@ -60,6 +52,12 @@ function filterByTimeRange(
6052 return data . filter ( ( d ) => d . date >= cutoffStr ) ;
6153}
6254
55+ // Format date for display
56+ const formatDate = ( dateStr : string ) => {
57+ const date = new Date ( dateStr ) ;
58+ return date . toLocaleDateString ( "en-US" , { month : "short" , day : "numeric" } ) ;
59+ } ;
60+
6361export function CostTrendChart ( { dailyActivity } : CostTrendChartProps ) {
6462 const [ timeRange , setTimeRange ] = useState < TimeRange > ( "30D" ) ;
6563
@@ -81,12 +79,6 @@ export function CostTrendChart({ dailyActivity }: CostTrendChartProps) {
8179 const totalCost = filteredData . reduce ( ( sum , d ) => sum + d . cost , 0 ) ;
8280 const avgCost = totalCost / filteredData . length ;
8381
84- // Format date for x-axis
85- const formatDate = ( dateStr : string ) => {
86- const date = new Date ( dateStr ) ;
87- return date . toLocaleDateString ( "en-US" , { month : "short" , day : "numeric" } ) ;
88- } ;
89-
9082 // Custom tooltip
9183 const CustomTooltip = ( {
9284 active,
@@ -99,75 +91,52 @@ export function CostTrendChart({ dailyActivity }: CostTrendChartProps) {
9991 } ) => {
10092 if ( ! active || ! payload || ! payload . length || ! label ) return null ;
10193 return (
102- < div className = "bg-white border border-[#232323] rounded-lg p-3 shadow-[2px_2px_0_#232323]" >
103- < p className = "font-bold text-sm mb-1" > { formatDate ( label ) } </ p >
104- < p className = "text-sm text-[#232323]/70" > { formatCurrency ( payload [ 0 ] . value ) } </ p >
105- </ div >
94+ < ChartTooltip
95+ title = { formatDate ( label ) }
96+ value = { formatCurrency ( payload [ 0 ] . value ) }
97+ / >
10698 ) ;
10799 } ;
108100
109101 const timeRangeOptions : TimeRange [ ] = [ "7D" , "30D" , "90D" ] ;
110102
111- return (
112- < div className = "card" >
113- < div className = "flex items-center justify-between mb-4" >
114- < div >
115- < h3 className = "font-bold" > Cost Trend</ h3 >
116- < p className = "text-xs text-[#232323]/50 mt-0.5" >
117- Total: { formatCurrency ( totalCost ) } | Avg: { formatCurrency ( avgCost ) } /day
118- </ p >
119- </ div >
120- < div className = "flex rounded-lg border border-[#232323]/20 overflow-hidden" >
121- { timeRangeOptions . map ( ( range ) => (
122- < button
123- key = { range }
124- onClick = { ( ) => setTimeRange ( range ) }
125- className = { `px-2.5 py-1 text-xs font-medium transition-colors ${
126- timeRange === range
127- ? "bg-[#232323] text-white"
128- : "bg-white text-[#232323]/70 hover:bg-[#232323]/5"
129- } `}
130- >
131- { range }
132- </ button >
133- ) ) }
134- </ div >
135- </ div >
136- < div className = "h-[250px]" >
137- < ResponsiveContainer width = "100%" height = "100%" >
138- < AreaChart data = { filteredData } margin = { { top : 5 , right : 20 , left : 10 , bottom : 5 } } >
139- < defs >
140- < linearGradient id = "costGradient" x1 = "0" y1 = "0" x2 = "0" y2 = "1" >
141- < stop offset = "5%" stopColor = "#D63384" stopOpacity = { 0.3 } />
142- < stop offset = "95%" stopColor = "#D63384" stopOpacity = { 0 } />
143- </ linearGradient >
144- </ defs >
145- < CartesianGrid strokeDasharray = "3 3" stroke = "#232323" strokeOpacity = { 0.1 } />
146- < XAxis
147- dataKey = "date"
148- tickFormatter = { formatDate }
149- tick = { { fontSize : 11 , fill : "#232323" , fillOpacity : 0.5 } }
150- tickLine = { false }
151- axisLine = { { stroke : "#232323" , strokeOpacity : 0.1 } }
152- />
153- < YAxis
154- tickFormatter = { ( v ) => `$${ v } ` }
155- tick = { { fontSize : 11 , fill : "#232323" , fillOpacity : 0.5 } }
156- tickLine = { false }
157- axisLine = { { stroke : "#232323" , strokeOpacity : 0.1 } }
158- width = { 50 }
159- />
160- < Tooltip content = { < CustomTooltip /> } />
161- < Area
162- type = "monotone"
163- dataKey = "cost"
164- stroke = "#D63384"
165- strokeWidth = { 2 }
166- fill = "url(#costGradient)"
167- />
168- </ AreaChart >
169- </ ResponsiveContainer >
170- </ div >
103+ const TimeRangeSelector = (
104+ < div className = "flex rounded-lg border border-[#232323]/20 overflow-hidden" >
105+ { timeRangeOptions . map ( ( range ) => (
106+ < button
107+ key = { range }
108+ onClick = { ( ) => setTimeRange ( range ) }
109+ className = { `px-2.5 py-1 text-xs font-medium transition-colors ${
110+ timeRange === range
111+ ? "bg-[#232323] text-white"
112+ : "bg-white text-[#232323]/70 hover:bg-[#232323]/5"
113+ } `}
114+ >
115+ { range }
116+ </ button >
117+ ) ) }
171118 </ div >
172119 ) ;
120+
121+ return (
122+ < ChartCard
123+ title = "Cost Trend"
124+ subtitle = { `Total: ${ formatCurrency ( totalCost ) } | Avg: ${ formatCurrency ( avgCost ) } /day` }
125+ rightSlot = { TimeRangeSelector }
126+ height = { 250 }
127+ >
128+ < AreaChart
129+ data = { filteredData }
130+ dataKey = "cost"
131+ xAxisKey = "date"
132+ color = "#D63384"
133+ gradient
134+ gradientId = "costTrendGradient"
135+ xAxisFormatter = { formatDate }
136+ yAxisFormatter = { ( v ) => `$${ v } ` }
137+ tooltipContent = { < CustomTooltip /> }
138+ height = { 250 }
139+ />
140+ </ ChartCard >
141+ ) ;
173142}
0 commit comments