Skip to content

Commit 2474a6e

Browse files
committed
fix
1 parent d224fbd commit 2474a6e

14 files changed

Lines changed: 496 additions & 314 deletions

app/api/coins/ohlc/route.ts

Lines changed: 0 additions & 54 deletions
This file was deleted.

app/coins/[id]/page.tsx

Lines changed: 5 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
1-
import { Badge } from '@/components/ui/badge';
21
import { Separator } from '@/components/ui/separator';
32
import { getCoinDetails, getCoinOHLC } from '@/lib/ coingecko.actions';
4-
import { cn, formatPercentage, formatPrice, timeAgo } from '@/lib/utils';
5-
import { ArrowUpRight, TrendingDown, TrendingUp } from 'lucide-react';
3+
import { formatPrice, timeAgo } from '@/lib/utils';
4+
import { ArrowUpRight } from 'lucide-react';
65

7-
import Image from 'next/image';
86
import Link from 'next/link';
97
import {
108
Table,
@@ -16,6 +14,7 @@ import {
1614
} from '@/components/ui/table';
1715
import { Converter } from '@/components/Converter';
1816
import CandlestickChart from '@/components/CandlestickChart';
17+
import LiveCoinHeader from '@/components/LiveCoinHeader';
1918

2019
const CoinDetails = async ({ params }: { params: Promise<{ id: string }> }) => {
2120
const { id } = await params;
@@ -45,97 +44,11 @@ const CoinDetails = async ({ params }: { params: Promise<{ id: string }> }) => {
4544
tickers: coinData.tickers,
4645
};
4746

48-
const isTrendingUp = coin.priceChangePercentage24h > 0;
49-
5047
return (
5148
<main className='py-12 container size-full grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 items-center gap-6 xl:gap-10 justify-center'>
5249
<section className='size-full xl:col-span-2'>
53-
{/* Coin Details */}
54-
<div className='space-y-5 w-full'>
55-
<h3 className='text-3xl font-medium'>{coin.name}</h3>
56-
<div className='flex gap-3 items-center'>
57-
<Image
58-
src={coin.image}
59-
alt={coin.name}
60-
width={77}
61-
height={77}
62-
className='size-[45px] sm:size-[50px] xl:size-[77px]'
63-
/>
64-
<div className='flex gap-4'>
65-
<h1 className='text-3xl sm:text-5xl xl:text-6xl font-semibold'>
66-
{formatPrice(coin.price)}
67-
</h1>
68-
<Badge
69-
className={cn(
70-
'font-medium mt-2 h-fit py-1 flex items-center gap-1',
71-
isTrendingUp
72-
? 'bg-green-500/20 text-green-600'
73-
: 'bg-red-500/20 text-red-500'
74-
)}
75-
>
76-
{formatPercentage(coin.priceChangePercentage24h)}
77-
{isTrendingUp ? <TrendingUp /> : <TrendingDown />}
78-
(24h)
79-
</Badge>
80-
</div>
81-
</div>
82-
<div className='grid grid-cols-3 mt-8 gap-4 sm:gap-6 w-fit'>
83-
{/* Today */}
84-
<div className='text-base border-r border-purple-600 flex flex-col gap-2'>
85-
<p className='text-purple-100 max-sm:text-sm'>Today</p>
86-
<div
87-
className={cn(
88-
'flex flex-1 gap-1 items-end text-sm font-medium',
89-
{
90-
'text-green-500': coin.priceChangePercentage24h > 0,
91-
'text-red-500': coin.priceChangePercentage24h < 0,
92-
}
93-
)}
94-
>
95-
<p>{formatPercentage(coin.priceChangePercentage24h)}</p>
96-
{isTrendingUp ? (
97-
<TrendingUp width={16} height={16} />
98-
) : (
99-
<TrendingDown width={16} height={16} />
100-
)}
101-
</div>
102-
</div>
103-
{/* 30 Days */}
104-
<div className='text-base border-r border-purple-600 flex flex-col gap-2'>
105-
<p className='text-purple-100 max-sm:text-sm'>30 Days</p>
106-
<div
107-
className={cn(
108-
'flex gap-1 flex-1 items-end text-sm font-medium',
109-
{
110-
'text-green-500': coin.priceChangePercentage30d > 0,
111-
'text-red-500': coin.priceChangePercentage30d < 0,
112-
}
113-
)}
114-
>
115-
<p>{formatPercentage(coin.priceChangePercentage30d)}</p>
116-
{isTrendingUp ? (
117-
<TrendingUp width={16} height={16} />
118-
) : (
119-
<TrendingDown width={16} height={16} />
120-
)}
121-
</div>
122-
</div>
123-
{/* Rank */}
124-
<div className='text-base flex flex-col gap-2'>
125-
<p className='text-purple-100 max-sm:text-sm'>
126-
Price Change (24h)
127-
</p>
128-
<p
129-
className={cn('flex gap-1 items-center text-sm font-medium', {
130-
'text-green-500': coin.priceChange24h > 0,
131-
'text-red-500': coin.priceChange24h < 0,
132-
})}
133-
>
134-
{formatPrice(coin.priceChange24h)}
135-
</p>
136-
</div>
137-
</div>
138-
</div>
50+
{/* Coin Details - Live */}
51+
<LiveCoinHeader coinId={coin.id} name={coin.name} image={coin.image} />
13952

14053
<Separator className='my-8 bg-purple-600' />
14154

app/layout.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import type { Metadata } from 'next';
22
import { Geist, Geist_Mono } from 'next/font/google';
33
import './globals.css';
44
import { Header } from '@/components/Header';
5-
import { getTrendingCoins, searchCoins } from '@/lib/ coingecko.actions';
5+
import { getTrendingCoins } from '@/lib/ coingecko.actions';
66

77
const geistSans = Geist({
88
variable: '--font-geist-sans',

app/page.tsx

Lines changed: 10 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,14 @@ import {
1616
TableRow,
1717
} from '@/components/ui/table';
1818

19-
import CandlestickChart from '@/components/CandlestickChart';
19+
import ChartSection from '@/components/ChartSection';
2020
import CoinCard from '@/components/CoinCard';
2121
import { popularCoins } from '@/lib/constants';
2222
import { TrendingDown, TrendingUp } from 'lucide-react';
2323

2424
const Home = async () => {
25-
const coinData = await getCoinDetails('bitcoin');
2625
const trendingCoins = await getTrendingCoins();
26+
const coinData = await getCoinDetails('bitcoin');
2727
const coinOHLCData = await getCoinOHLC(
2828
'bitcoin',
2929
30, // days
@@ -32,33 +32,15 @@ const Home = async () => {
3232
'full' // precision
3333
);
3434

35-
console.log('trendingCoins:', trendingCoins);
36-
3735
return (
3836
<main className='py-6 md:py-12 container size-full space-y-6 md:space-y-6'>
39-
<section className='grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 items-start lg:items-center gap-6 xl:gap-10'>
37+
<section className='grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 items-start lg:items-center gap-6'>
4038
{/* Coin Overview */}
41-
<div className='w-full h-full xl:col-span-2 px-2 py-3 bg-dark-500 rounded-xl'>
42-
<CandlestickChart data={coinOHLCData} coinId={'bitcoin'}>
43-
<div className='flex-1 mb-2 flex gap-2 md:gap-3'>
44-
<Image
45-
src={coinData.image.large}
46-
alt={coinData.name}
47-
width={56}
48-
height={56}
49-
className='w-10 h-10 md:w-14 md:h-14'
50-
/>
51-
<div className='flex flex-col'>
52-
<p className='flex text-purple-100 text-xs md:text-sm w-fit'>
53-
{coinData.name} / {coinData.symbol.toUpperCase()}
54-
</p>
55-
<h1 className='text-xl md:text-2xl font-semibold'>
56-
{formatPrice(coinData.market_data.current_price.usd)}
57-
</h1>
58-
</div>
59-
</div>
60-
</CandlestickChart>
61-
</div>
39+
<ChartSection
40+
coinData={coinData}
41+
coinOHLCData={coinOHLCData}
42+
coinId='bitcoin'
43+
/>
6244

6345
{/* Top Movers */}
6446
<div className='w-full flex flex-col justify-center h-full py-4 bg-dark-500 rounded-xl'>
@@ -141,7 +123,7 @@ const Home = async () => {
141123
</div>
142124
</section>
143125

144-
{/* <section className='w-full grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4 md:gap-6'>
126+
<section className='w-full grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4 md:gap-6'>
145127
{popularCoins.map((coin) => (
146128
<CoinCard
147129
key={coin.coinId}
@@ -151,7 +133,7 @@ const Home = async () => {
151133
image={coin.image}
152134
/>
153135
))}
154-
</section> */}
136+
</section>
155137
</main>
156138
);
157139
};

components/CandlestickChart.tsx

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -38,22 +38,18 @@ export default function CandlestickChart({
3838
setLoading(true);
3939
try {
4040
const config = PERIOD_CONFIG[selectedPeriod];
41-
const params = new URLSearchParams({
42-
id: coinId,
43-
days: String(config.days),
44-
currency: 'usd',
45-
precision: 'full',
46-
});
4741

48-
// Only add interval if it's defined (not for yearly/max)
49-
if (config.interval) {
50-
params.append('interval', config.interval);
51-
}
42+
// Dynamically import the server action
43+
const { getCoinOHLC } = await import('@/lib/ coingecko.actions');
5244

53-
const response = await fetch(`/api/coins/ohlc?${params}`);
54-
if (!response.ok) throw new Error('Failed to fetch OHLC data');
45+
const newData = await getCoinOHLC(
46+
coinId,
47+
config.days,
48+
'usd',
49+
config.interval,
50+
'full'
51+
);
5552

56-
const newData = await response.json();
5753
setOhlcData(newData);
5854
} catch (error) {
5955
console.error('Error fetching OHLC data:', error);

components/ChartSection.tsx

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
'use client';
2+
3+
import Image from 'next/image';
4+
import { formatPrice } from '@/lib/utils';
5+
import CandlestickChart from './CandlestickChart';
6+
7+
export default function ChartSection({
8+
coinData,
9+
coinOHLCData,
10+
coinId,
11+
}: ChartSectionProps) {
12+
return (
13+
<div className='w-full h-full xl:col-span-2 px-2 py-3 bg-dark-500 rounded-xl'>
14+
<CandlestickChart data={coinOHLCData} coinId={coinId}>
15+
<div className='flex-1 mb-2 flex gap-2 md:gap-3'>
16+
<Image
17+
src={coinData.image.large}
18+
alt={coinData.name}
19+
width={56}
20+
height={56}
21+
className='w-10 h-10 md:w-14 md:h-14'
22+
/>
23+
<div className='flex flex-col'>
24+
<p className='flex text-purple-100 text-xs md:text-sm w-fit'>
25+
{coinData.name} / {coinData.symbol.toUpperCase()}
26+
</p>
27+
<h1 className='text-xl md:text-2xl font-semibold'>
28+
{formatPrice(coinData.market_data.current_price.usd)}
29+
</h1>
30+
</div>
31+
</div>
32+
</CandlestickChart>
33+
</div>
34+
);
35+
}

0 commit comments

Comments
 (0)