UsageChartTooltips.tsx 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. import type { Payload, ValueType } from 'recharts/types/component/DefaultTooltipContent'
  2. import { cn } from 'ui'
  3. import { Attribute, COLOR_MAP } from './Usage.constants'
  4. export interface SingleAttributeTooltipContentProps {
  5. name: string
  6. unit: 'bytes' | 'percentage' | 'absolute' | 'hours' | 'gigabytes'
  7. value: any
  8. isAfterToday: boolean
  9. tooltipFormatter?: (value: any) => any
  10. }
  11. export const SingleAttributeTooltipContent = ({
  12. name,
  13. unit,
  14. value,
  15. isAfterToday,
  16. tooltipFormatter,
  17. }: SingleAttributeTooltipContentProps) => {
  18. const formattedValue = unit === 'percentage' ? Number(value).toFixed(2) : Number(value)
  19. return (
  20. <>
  21. <p className="text-xs text-foreground-light">{name}</p>
  22. {isAfterToday ? (
  23. <p className="text-foreground-light text-lg">No data yet</p>
  24. ) : (
  25. <p className="text-xl">
  26. {tooltipFormatter !== undefined ? tooltipFormatter(formattedValue) : formattedValue}
  27. </p>
  28. )}
  29. </>
  30. )
  31. }
  32. export interface MultiAttributeTooltipContentProps {
  33. attributes: Attribute[]
  34. values: Payload<ValueType, string | number>[]
  35. isAfterToday: boolean
  36. tooltipFormatter?: (value: any) => any
  37. unit: 'bytes' | 'percentage' | 'absolute' | 'hours' | 'gigabytes'
  38. }
  39. const AttributeContent = ({
  40. attribute,
  41. attributeMeta,
  42. sumValue,
  43. tooltipFormatter,
  44. unit,
  45. }: {
  46. attribute: Attribute
  47. attributeMeta?: Payload<ValueType, string | number>
  48. sumValue: number
  49. tooltipFormatter?: (value: any) => any
  50. unit: 'bytes' | 'percentage' | 'absolute' | 'hours' | 'gigabytes'
  51. }) => {
  52. const attrValue = Number(attributeMeta?.value ?? 0)
  53. const percentageContribution = ((attrValue / sumValue) * 100).toFixed(1)
  54. return (
  55. <div key={attribute.name} className="flex items-center justify-between">
  56. <div className="flex items-center space-x-2 w-[175px]">
  57. <div className={cn('w-3 h-3 rounded-full border', COLOR_MAP[attribute.color].marker)} />
  58. <p className="text-xs prose">
  59. {attribute.name} ({percentageContribution}%):{' '}
  60. </p>
  61. </div>
  62. <p className="text-xs tabular-nums">
  63. {tooltipFormatter !== undefined
  64. ? tooltipFormatter(attrValue)
  65. : `${attrValue}${unit === 'hours' ? ' H' : ''}`}
  66. </p>
  67. </div>
  68. )
  69. }
  70. export const MultiAttributeTooltipContent = ({
  71. attributes,
  72. values,
  73. isAfterToday,
  74. tooltipFormatter,
  75. unit,
  76. }: MultiAttributeTooltipContentProps) => {
  77. const sumValue = values.reduce((a, b) => a + Number(b.value), 0)
  78. return (
  79. <>
  80. {isAfterToday ? (
  81. <p className="text-foreground-light text-lg">No data yet</p>
  82. ) : (
  83. <div className="space-y-1 pb-1">
  84. {attributes.flatMap((attr) => {
  85. const attributeMeta = values.find((x) => x.dataKey === attr.key)
  86. // Filter out empty attributes
  87. if (Number(attributeMeta?.value ?? 0) === 0) return []
  88. return (
  89. <AttributeContent
  90. key={attr.name}
  91. attribute={attr}
  92. attributeMeta={attributeMeta}
  93. sumValue={sumValue}
  94. tooltipFormatter={tooltipFormatter}
  95. unit={unit}
  96. />
  97. )
  98. })}
  99. </div>
  100. )}
  101. </>
  102. )
  103. }