Compare commits
4 Commits
045d4a41e3
...
23cab77200
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
23cab77200 | ||
|
|
1e65f5d87a | ||
|
|
65994816ab | ||
|
|
8087806a16 |
27
app/api/image/route.ts
Normal file
27
app/api/image/route.ts
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import { NextRequest, NextResponse } from 'next/server'
|
||||||
|
import fs from 'fs/promises'
|
||||||
|
import path from 'path'
|
||||||
|
|
||||||
|
export async function GET(req: NextRequest) {
|
||||||
|
try {
|
||||||
|
const { searchParams } = new URL(req.url)
|
||||||
|
const filename = searchParams.get('file')
|
||||||
|
|
||||||
|
if (!filename) {
|
||||||
|
return NextResponse.json({ error: 'Filename required' }, { status: 400 })
|
||||||
|
}
|
||||||
|
|
||||||
|
const screenshotsDir = path.join(process.cwd(), 'screenshots')
|
||||||
|
const filePath = path.join(screenshotsDir, filename)
|
||||||
|
const file = await fs.readFile(filePath)
|
||||||
|
|
||||||
|
return new NextResponse(file, {
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'image/png',
|
||||||
|
'Content-Disposition': `inline; filename="${filename}"`
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} catch (e: any) {
|
||||||
|
return NextResponse.json({ error: e.message }, { status: 404 })
|
||||||
|
}
|
||||||
|
}
|
||||||
12
app/api/test-gallery/route.ts
Normal file
12
app/api/test-gallery/route.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import { NextRequest, NextResponse } from 'next/server'
|
||||||
|
|
||||||
|
export async function GET(req: NextRequest) {
|
||||||
|
return NextResponse.json({
|
||||||
|
message: 'Test endpoint working',
|
||||||
|
timestamp: new Date().toISOString(),
|
||||||
|
screenshots: [
|
||||||
|
'/app/screenshots/SOLUSD_240_ai_1752448407811.png',
|
||||||
|
'/app/screenshots/SOLUSD_15_ai_1752441315672.png'
|
||||||
|
]
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
import { NextRequest, NextResponse } from 'next/server'
|
|
||||||
import fs from 'fs/promises'
|
|
||||||
import path from 'path'
|
|
||||||
|
|
||||||
export async function GET(
|
|
||||||
request: NextRequest,
|
|
||||||
context: any
|
|
||||||
) {
|
|
||||||
try {
|
|
||||||
const screenshotsDir = path.join(process.cwd(), 'screenshots')
|
|
||||||
const filePath = path.join(screenshotsDir, context.params.filename)
|
|
||||||
const file = await fs.readFile(filePath)
|
|
||||||
return new NextResponse(file, {
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'image/png',
|
|
||||||
'Content-Disposition': `inline; filename="${context.params.filename}"`
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} catch (e: any) {
|
|
||||||
return NextResponse.json({ error: e.message }, { status: 404 })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -38,8 +38,8 @@ export default function ScreenshotGallery({
|
|||||||
const formatScreenshotUrl = (screenshot: string) => {
|
const formatScreenshotUrl = (screenshot: string) => {
|
||||||
// Extract just the filename from the full path
|
// Extract just the filename from the full path
|
||||||
const filename = screenshot.split('/').pop() || screenshot
|
const filename = screenshot.split('/').pop() || screenshot
|
||||||
// Return the Next.js API route format
|
// Use the new API route with query parameter
|
||||||
return `/screenshots/${filename}`
|
return `/api/image?file=${filename}`
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -61,7 +61,20 @@ export default function ScreenshotGallery({
|
|||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||||
{screenshots.map((screenshot, index) => {
|
{screenshots.map((screenshot, index) => {
|
||||||
const filename = screenshot.split('/').pop() || ''
|
const filename = screenshot.split('/').pop() || ''
|
||||||
const timeframe = timeframes[index] || 'Unknown'
|
// Extract timeframe from filename (e.g., SOLUSD_5_ai_timestamp.png -> "5m")
|
||||||
|
const extractTimeframeFromFilename = (filename: string) => {
|
||||||
|
const match = filename.match(/_(\d+|D)_/)
|
||||||
|
if (!match) return 'Unknown'
|
||||||
|
const tf = match[1]
|
||||||
|
if (tf === 'D') return '1D'
|
||||||
|
if (tf === '5') return '5m'
|
||||||
|
if (tf === '15') return '15m'
|
||||||
|
if (tf === '60') return '1h'
|
||||||
|
if (tf === '240') return '4h'
|
||||||
|
return `${tf}m`
|
||||||
|
}
|
||||||
|
|
||||||
|
const timeframe = timeframes[index] || extractTimeframeFromFilename(filename)
|
||||||
const imageUrl = formatScreenshotUrl(screenshot)
|
const imageUrl = formatScreenshotUrl(screenshot)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 273 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 270 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 125 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 265 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 264 KiB |
124
test-gallery.html
Normal file
124
test-gallery.html
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Test Screenshot Gallery</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
background: #111;
|
||||||
|
color: white;
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
margin: 20px;
|
||||||
|
}
|
||||||
|
.gallery {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||||
|
gap: 20px;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
.screenshot {
|
||||||
|
border: 1px solid #333;
|
||||||
|
border-radius: 8px;
|
||||||
|
overflow: hidden;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.screenshot img {
|
||||||
|
width: 100%;
|
||||||
|
height: 200px;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
.screenshot:hover {
|
||||||
|
border-color: #666;
|
||||||
|
}
|
||||||
|
.modal {
|
||||||
|
display: none;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: rgba(0,0,0,0.8);
|
||||||
|
z-index: 1000;
|
||||||
|
}
|
||||||
|
.modal img {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
max-width: 90%;
|
||||||
|
max-height: 90%;
|
||||||
|
}
|
||||||
|
.close {
|
||||||
|
position: absolute;
|
||||||
|
top: 20px;
|
||||||
|
right: 20px;
|
||||||
|
color: white;
|
||||||
|
font-size: 24px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Screenshot Gallery Test</h1>
|
||||||
|
<p>Testing direct screenshot access:</p>
|
||||||
|
|
||||||
|
<div class="gallery">
|
||||||
|
<div class="screenshot">
|
||||||
|
<img src="/screenshots/SOLUSD_240_ai_1752447978639.png" alt="SOLUSD 4h">
|
||||||
|
<div style="padding: 10px;">SOLUSD - 4h Timeframe</div>
|
||||||
|
</div>
|
||||||
|
<div class="screenshot">
|
||||||
|
<img src="/screenshots/SOLUSD_15_ai_1752441315672.png" alt="SOLUSD 15m">
|
||||||
|
<div style="padding: 10px;">SOLUSD - 15m Timeframe</div>
|
||||||
|
</div>
|
||||||
|
<div class="screenshot">
|
||||||
|
<img src="/screenshots/SOLUSD_5_ai_1752441274081.png" alt="SOLUSD 5m">
|
||||||
|
<div style="padding: 10px;">SOLUSD - 5m Timeframe</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="modal" class="modal">
|
||||||
|
<span class="close">×</span>
|
||||||
|
<img id="modalImg" src="" alt="">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const screenshots = document.querySelectorAll('.screenshot img');
|
||||||
|
const modal = document.getElementById('modal');
|
||||||
|
const modalImg = document.getElementById('modalImg');
|
||||||
|
const close = document.querySelector('.close');
|
||||||
|
|
||||||
|
screenshots.forEach(img => {
|
||||||
|
img.addEventListener('click', function() {
|
||||||
|
modal.style.display = 'block';
|
||||||
|
modalImg.src = this.src;
|
||||||
|
console.log('Image clicked:', this.src);
|
||||||
|
});
|
||||||
|
|
||||||
|
img.addEventListener('load', function() {
|
||||||
|
console.log('Image loaded:', this.src);
|
||||||
|
});
|
||||||
|
|
||||||
|
img.addEventListener('error', function() {
|
||||||
|
console.error('Image failed to load:', this.src);
|
||||||
|
this.style.border = '2px solid red';
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
close.addEventListener('click', function() {
|
||||||
|
modal.style.display = 'none';
|
||||||
|
});
|
||||||
|
|
||||||
|
document.addEventListener('keydown', function(e) {
|
||||||
|
if (e.key === 'Escape') {
|
||||||
|
modal.style.display = 'none';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
modal.addEventListener('click', function(e) {
|
||||||
|
if (e.target === modal) {
|
||||||
|
modal.style.display = 'none';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user