1
0

price-chart.tsx 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. "use client"
  2. import { useMemo, useState } from "react"
  3. import { Line } from "react-chartjs-2"
  4. import {
  5. Chart as ChartJS,
  6. CategoryScale,
  7. LinearScale,
  8. PointElement,
  9. LineElement,
  10. Title,
  11. Tooltip,
  12. Legend,
  13. TimeScale,
  14. } from "chart.js"
  15. import "chartjs-adapter-date-fns"
  16. import { Button } from "./ui/button"
  17. ChartJS.register(CategoryScale, LinearScale, PointElement, LineElement, Title, Tooltip, Legend, TimeScale)
  18. const timeFrames = [
  19. { label: "1D", ms: 1 * 24 * 60 * 60 * 1000 },
  20. { label: "1W", ms: 7 * 24 * 60 * 60 * 1000 },
  21. { label: "1M", ms: 30 * 24 * 60 * 60 * 1000 },
  22. { label: "3M", ms: 90 * 24 * 60 * 60 * 1000 },
  23. { label: "1Y", ms: 365 * 24 * 60 * 60 * 1000 },
  24. { label: "All", ms: Infinity },
  25. ]
  26. const getTimeUnit = (label: string): "minute" | "hour" | "day" | "month" => {
  27. switch (label) {
  28. case "1D":
  29. return "minute"
  30. case "1W":
  31. return "hour"
  32. case "1M":
  33. case "3M":
  34. return "day"
  35. case "1Y":
  36. return "month"
  37. default:
  38. return "day"
  39. }
  40. }
  41. export function PriceChart({ priceHistory }: { priceHistory: { x: string; y: number }[] }) {
  42. const [selectedTimeFrame, setSelectedTimeFrame] = useState(timeFrames[2]) // Default: 1M
  43. const latestTimestamp = useMemo(() => {
  44. return priceHistory.length > 0
  45. ? new Date(priceHistory[priceHistory.length - 1].x).getTime()
  46. : Date.now()
  47. }, [priceHistory])
  48. const filteredData = useMemo(() => {
  49. if (selectedTimeFrame.ms === Infinity) return priceHistory
  50. return priceHistory.filter((d) => new Date(d.x).getTime() >= latestTimestamp - selectedTimeFrame.ms)
  51. }, [priceHistory, selectedTimeFrame, latestTimestamp])
  52. const chartData = {
  53. datasets: [
  54. {
  55. label: "Price",
  56. data: filteredData,
  57. borderColor: "rgb(59, 130, 246)",
  58. backgroundColor: "rgba(59, 130, 246, 0.5)",
  59. borderWidth: 2,
  60. pointRadius: 0,
  61. tension: 0.1,
  62. },
  63. ],
  64. }
  65. const chartOptions = useMemo(() => ({
  66. responsive: true,
  67. interaction: {
  68. mode: "index" as const,
  69. intersect: false,
  70. },
  71. plugins: {
  72. legend: { display: false },
  73. title: { display: false },
  74. },
  75. scales: {
  76. x: {
  77. type: "time" as const,
  78. time: {
  79. unit: getTimeUnit(selectedTimeFrame.label),
  80. },
  81. grid: { display: false },
  82. },
  83. y: {
  84. position: "right" as const,
  85. grid: {
  86. color: "rgba(107, 114, 128, 0.1)",
  87. },
  88. ticks: {
  89. callback: (value: any) => `$${value.toLocaleString()}`,
  90. },
  91. },
  92. },
  93. }), [selectedTimeFrame])
  94. return (
  95. <div className="bg-white p-6 rounded-lg border border-gray-200 shadow-sm">
  96. <div className="flex justify-between items-center mb-4">
  97. <div className="text-2xl font-bold font-orbitron text-gray-800">
  98. {priceHistory.length ? `${priceHistory[priceHistory.length - 1].y.toFixed(4)} AIUS` : "Loading..."}
  99. </div>
  100. <div className="flex space-x-2">
  101. {timeFrames.map((tf) => (
  102. <Button
  103. key={tf.label}
  104. variant={selectedTimeFrame.label === tf.label ? "default" : "outline"}
  105. size="sm"
  106. onClick={() => setSelectedTimeFrame(tf)}
  107. className="font-roboto-mono"
  108. >
  109. {tf.label}
  110. </Button>
  111. ))}
  112. </div>
  113. </div>
  114. <Line options={chartOptions} data={chartData} />
  115. </div>
  116. )
  117. }