Fix ScreenshotGallery and improve trade execution feedback
- Add keyboard ESC listener for closing enlarged screenshots - Fix screenshot URL formatting to use /screenshots/[filename] route - Improve trade execution error handling with detailed messages - Show specific feedback for insufficient funds, auth issues, etc. - Remove unused Modal import that was causing build errors - Add click-outside-to-close functionality for enlarged images
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
"use client"
|
||||
import React, { useState } from 'react'
|
||||
import Modal from './Modal'
|
||||
import TradeModal from './TradeModal'
|
||||
import ScreenshotGallery from './ScreenshotGallery'
|
||||
|
||||
@@ -420,27 +419,50 @@ export default function AIAnalysisPanel() {
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
symbol: tradeData.symbol,
|
||||
side: 'buy', // Could be derived from analysis
|
||||
size: parseFloat(tradeData.size),
|
||||
side: 'BUY', // Could be derived from analysis
|
||||
amount: parseFloat(tradeData.size), // Changed from 'size' to 'amount'
|
||||
price: parseFloat(tradeData.entry),
|
||||
stopLoss: parseFloat(tradeData.sl),
|
||||
takeProfit: parseFloat(tradeData.tp),
|
||||
leverage: parseInt(tradeData.leverage),
|
||||
timeframe: tradeData.timeframe
|
||||
timeframe: tradeData.timeframe,
|
||||
orderType: 'MARKET' // Default to market order
|
||||
})
|
||||
})
|
||||
|
||||
const result = await response.json()
|
||||
|
||||
if (response.ok) {
|
||||
// Show success message
|
||||
alert(`Trade executed successfully! Order ID: ${result.orderId || 'N/A'}`)
|
||||
if (response.ok && result.success) {
|
||||
// Show detailed success message
|
||||
let message = `✅ Trade executed successfully!\n\n`
|
||||
message += `📊 Order ID: ${result.txId}\n`
|
||||
message += `💰 Symbol: ${tradeData.symbol}\n`
|
||||
message += `📈 Size: ${tradeData.size}\n`
|
||||
message += `💵 Entry: $${tradeData.entry}\n`
|
||||
|
||||
if (tradeData.sl) message += `🛑 Stop Loss: $${tradeData.sl}\n`
|
||||
if (tradeData.tp) message += `🎯 Take Profit: $${tradeData.tp}\n`
|
||||
|
||||
if (result.conditionalOrders && result.conditionalOrders.length > 0) {
|
||||
message += `\n🔄 Conditional orders: ${result.conditionalOrders.length} placed`
|
||||
}
|
||||
|
||||
alert(message)
|
||||
} else {
|
||||
alert(`Trade failed: ${result.error || 'Unknown error'}`)
|
||||
// Show detailed error message
|
||||
const errorMsg = result.error || 'Unknown error occurred'
|
||||
|
||||
if (errorMsg.includes('insufficient funds') || errorMsg.includes('balance')) {
|
||||
alert(`❌ Trade Failed: Insufficient Balance\n\nPlease deposit funds to your Drift account before placing trades.\n\nError: ${errorMsg}`)
|
||||
} else if (errorMsg.includes('not logged in') || errorMsg.includes('Cannot execute trade')) {
|
||||
alert(`❌ Trade Failed: Authentication Issue\n\nPlease check your Drift connection in the settings.\n\nError: ${errorMsg}`)
|
||||
} else {
|
||||
alert(`❌ Trade Failed\n\nError: ${errorMsg}`)
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Trade execution failed:', error)
|
||||
alert('Trade execution failed. Please check your connection.')
|
||||
alert('❌ Trade execution failed due to network error.\n\nPlease check your connection and try again.')
|
||||
}
|
||||
|
||||
setTradeModalOpen(false)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
"use client"
|
||||
import React from 'react'
|
||||
import React, { useEffect } from 'react'
|
||||
|
||||
interface ScreenshotGalleryProps {
|
||||
screenshots: string[]
|
||||
@@ -18,8 +18,30 @@ export default function ScreenshotGallery({
|
||||
onImageClick,
|
||||
onClose
|
||||
}: ScreenshotGalleryProps) {
|
||||
// Handle ESC key to close enlarged image
|
||||
useEffect(() => {
|
||||
const handleKeyDown = (event: KeyboardEvent) => {
|
||||
if (event.key === 'Escape' && enlargedImage) {
|
||||
onClose()
|
||||
}
|
||||
}
|
||||
|
||||
if (enlargedImage) {
|
||||
document.addEventListener('keydown', handleKeyDown)
|
||||
return () => document.removeEventListener('keydown', handleKeyDown)
|
||||
}
|
||||
}, [enlargedImage, onClose])
|
||||
|
||||
if (screenshots.length === 0) return null
|
||||
|
||||
// Helper function to format screenshot URL
|
||||
const formatScreenshotUrl = (screenshot: string) => {
|
||||
// Extract just the filename from the full path
|
||||
const filename = screenshot.split('/').pop() || screenshot
|
||||
// Return the Next.js API route format
|
||||
return `/screenshots/${filename}`
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* Gallery Grid */}
|
||||
@@ -40,23 +62,25 @@ export default function ScreenshotGallery({
|
||||
{screenshots.map((screenshot, index) => {
|
||||
const filename = screenshot.split('/').pop() || ''
|
||||
const timeframe = timeframes[index] || 'Unknown'
|
||||
const imageUrl = formatScreenshotUrl(screenshot)
|
||||
|
||||
return (
|
||||
<div
|
||||
key={index}
|
||||
className="group relative bg-gray-800/30 rounded-lg overflow-hidden border border-gray-700 hover:border-purple-500/50 transition-all cursor-pointer transform hover:scale-[1.02]"
|
||||
onClick={() => onImageClick(screenshot)}
|
||||
onClick={() => onImageClick(imageUrl)}
|
||||
>
|
||||
{/* Preview Image */}
|
||||
<div className="aspect-video bg-gray-800 flex items-center justify-center relative">
|
||||
<img
|
||||
src={screenshot}
|
||||
src={imageUrl}
|
||||
alt={`${symbol} - ${timeframe} chart`}
|
||||
className="w-full h-full object-cover"
|
||||
onError={(e) => {
|
||||
onError={(e: any) => {
|
||||
const target = e.target as HTMLImageElement
|
||||
target.style.display = 'none'
|
||||
target.nextElementSibling?.classList.remove('hidden')
|
||||
const fallback = target.nextElementSibling as HTMLElement
|
||||
if (fallback) fallback.classList.remove('hidden')
|
||||
}}
|
||||
/>
|
||||
<div className="hidden absolute inset-0 flex items-center justify-center text-gray-400">
|
||||
@@ -97,8 +121,11 @@ export default function ScreenshotGallery({
|
||||
|
||||
{/* Enlarged Image Modal */}
|
||||
{enlargedImage && (
|
||||
<div className="fixed inset-0 bg-black/80 backdrop-blur-sm flex items-center justify-center p-4 z-50">
|
||||
<div className="relative max-w-6xl max-h-[90vh] w-full">
|
||||
<div
|
||||
className="fixed inset-0 bg-black/80 backdrop-blur-sm flex items-center justify-center p-4 z-50"
|
||||
onClick={onClose}
|
||||
>
|
||||
<div className="relative max-w-6xl max-h-[90vh] w-full" onClick={(e: any) => e.stopPropagation()}>
|
||||
{/* Close Button */}
|
||||
<button
|
||||
onClick={onClose}
|
||||
@@ -112,6 +139,11 @@ export default function ScreenshotGallery({
|
||||
src={enlargedImage}
|
||||
alt="Enlarged chart"
|
||||
className="w-full h-full object-contain rounded-lg border border-gray-600"
|
||||
onError={(e: any) => {
|
||||
console.error('Failed to load enlarged image:', enlargedImage)
|
||||
const target = e.target as HTMLImageElement
|
||||
target.alt = 'Failed to load image'
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* Image Info Overlay */}
|
||||
@@ -122,7 +154,7 @@ export default function ScreenshotGallery({
|
||||
<div className="text-gray-300 text-sm">AI analyzed screenshot • High resolution view</div>
|
||||
</div>
|
||||
<div className="text-xs text-gray-400">
|
||||
ESC to close
|
||||
ESC to close • Click outside to close
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user