Fix layout names to match exact TradingView account names
- Use exact layout names: 'ai' and 'Diy module' (as in TradingView) - Update default selected layouts to ['ai', 'Diy module'] - Keep display names exactly as they appear in TradingView - Add lowercase fallback mapping in backend for 'diy module' - Remove normalization that was changing the exact names This ensures UI shows exactly what's in the TradingView account and selection state matches display.
This commit is contained in:
@@ -4,6 +4,12 @@ import TradeModal from './TradeModal'
|
|||||||
import ScreenshotGallery from './ScreenshotGallery'
|
import ScreenshotGallery from './ScreenshotGallery'
|
||||||
|
|
||||||
const layouts = (process.env.NEXT_PUBLIC_TRADINGVIEW_LAYOUTS || 'ai,Diy module').split(',').map(l => l.trim())
|
const layouts = (process.env.NEXT_PUBLIC_TRADINGVIEW_LAYOUTS || 'ai,Diy module').split(',').map(l => l.trim())
|
||||||
|
|
||||||
|
// Layout display names mapping
|
||||||
|
const layoutDisplayNames: { [key: string]: string } = {
|
||||||
|
'ai': 'ai',
|
||||||
|
'Diy module': 'Diy module'
|
||||||
|
}
|
||||||
const timeframes = [
|
const timeframes = [
|
||||||
{ label: '1m', value: '1' },
|
{ label: '1m', value: '1' },
|
||||||
{ label: '5m', value: '5' },
|
{ label: '5m', value: '5' },
|
||||||
@@ -57,7 +63,7 @@ interface AIAnalysisPanelProps {
|
|||||||
|
|
||||||
export default function AIAnalysisPanel({ onAnalysisComplete }: AIAnalysisPanelProps = {}) {
|
export default function AIAnalysisPanel({ onAnalysisComplete }: AIAnalysisPanelProps = {}) {
|
||||||
const [symbol, setSymbol] = useState('BTCUSD')
|
const [symbol, setSymbol] = useState('BTCUSD')
|
||||||
const [selectedLayouts, setSelectedLayouts] = useState<string[]>(['ai', 'diy']) // Default to both AI and DIY
|
const [selectedLayouts, setSelectedLayouts] = useState<string[]>(['ai', 'Diy module']) // Default to both layouts
|
||||||
const [selectedTimeframes, setSelectedTimeframes] = useState<string[]>(['60']) // Support multiple timeframes
|
const [selectedTimeframes, setSelectedTimeframes] = useState<string[]>(['60']) // Support multiple timeframes
|
||||||
const [loading, setLoading] = useState(false)
|
const [loading, setLoading] = useState(false)
|
||||||
const [result, setResult] = useState<any>(null)
|
const [result, setResult] = useState<any>(null)
|
||||||
@@ -134,11 +140,25 @@ export default function AIAnalysisPanel({ onAnalysisComplete }: AIAnalysisPanelP
|
|||||||
}
|
}
|
||||||
}, [eventSource])
|
}, [eventSource])
|
||||||
|
|
||||||
|
// Normalize layout key to match backend expectations
|
||||||
|
const normalizeLayoutKey = (layout: string): string => {
|
||||||
|
// Keep the exact names as they appear in TradingView
|
||||||
|
if (layout === 'ai') return 'ai'
|
||||||
|
if (layout === 'Diy module') return 'Diy module'
|
||||||
|
return layout
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get display name for layout (keep exact TradingView names)
|
||||||
|
const getLayoutDisplayName = (layout: string): string => {
|
||||||
|
return layoutDisplayNames[layout] || layout
|
||||||
|
}
|
||||||
|
|
||||||
const toggleLayout = (layout: string) => {
|
const toggleLayout = (layout: string) => {
|
||||||
|
const normalizedLayout = normalizeLayoutKey(layout)
|
||||||
setSelectedLayouts(prev =>
|
setSelectedLayouts(prev =>
|
||||||
prev.includes(layout)
|
prev.includes(normalizedLayout)
|
||||||
? prev.filter(l => l !== layout)
|
? prev.filter(l => l !== normalizedLayout)
|
||||||
: [...prev, layout]
|
: [...prev, normalizedLayout]
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -680,39 +700,47 @@ export default function AIAnalysisPanel({ onAnalysisComplete }: AIAnalysisPanelP
|
|||||||
<div className="mb-6">
|
<div className="mb-6">
|
||||||
<label className="block text-xs font-medium text-gray-400 mb-3">Analysis Layouts</label>
|
<label className="block text-xs font-medium text-gray-400 mb-3">Analysis Layouts</label>
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-3">
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-3">
|
||||||
{layouts.map(layout => (
|
{layouts.map(layout => {
|
||||||
<label key={layout} className="group relative">
|
const normalizedLayout = normalizeLayoutKey(layout)
|
||||||
<input
|
const displayName = getLayoutDisplayName(layout)
|
||||||
type="checkbox"
|
const isSelected = selectedLayouts.includes(normalizedLayout)
|
||||||
checked={selectedLayouts.includes(layout)}
|
|
||||||
onChange={() => toggleLayout(layout)}
|
return (
|
||||||
className="sr-only"
|
<label key={layout} className="group relative">
|
||||||
/>
|
<input
|
||||||
<div className={`flex items-center p-3 rounded-lg border cursor-pointer transition-all ${
|
type="checkbox"
|
||||||
selectedLayouts.includes(layout)
|
checked={isSelected}
|
||||||
? 'border-cyan-500 bg-cyan-500/10 text-cyan-300'
|
onChange={() => toggleLayout(layout)}
|
||||||
: 'border-gray-700 bg-gray-800/30 text-gray-300 hover:border-gray-600 hover:bg-gray-800/50'
|
className="sr-only"
|
||||||
}`}>
|
/>
|
||||||
<div className={`w-4 h-4 rounded border-2 mr-3 flex items-center justify-center ${
|
<div className={`flex items-center p-3 rounded-lg border cursor-pointer transition-all ${
|
||||||
selectedLayouts.includes(layout)
|
isSelected
|
||||||
? 'border-cyan-500 bg-cyan-500'
|
? 'border-cyan-500 bg-cyan-500/10 text-cyan-300'
|
||||||
: 'border-gray-600'
|
: 'border-gray-700 bg-gray-800/30 text-gray-300 hover:border-gray-600 hover:bg-gray-800/50'
|
||||||
}`}>
|
}`}>
|
||||||
{selectedLayouts.includes(layout) && (
|
<div className={`w-4 h-4 rounded border-2 mr-3 flex items-center justify-center ${
|
||||||
<svg className="w-2 h-2 text-white" fill="currentColor" viewBox="0 0 20 20">
|
isSelected
|
||||||
<path fillRule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clipRule="evenodd" />
|
? 'border-cyan-500 bg-cyan-500'
|
||||||
</svg>
|
: 'border-gray-600'
|
||||||
)}
|
}`}>
|
||||||
|
{isSelected && (
|
||||||
|
<svg className="w-2 h-2 text-white" fill="currentColor" viewBox="0 0 20 20">
|
||||||
|
<path fillRule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clipRule="evenodd" />
|
||||||
|
</svg>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<span className="text-sm font-medium">{displayName}</span>
|
||||||
</div>
|
</div>
|
||||||
<span className="text-sm font-medium">{layout}</span>
|
</label>
|
||||||
</div>
|
)
|
||||||
</label>
|
})}
|
||||||
))}
|
|
||||||
</div>
|
</div>
|
||||||
{selectedLayouts.length > 0 && (
|
{selectedLayouts.length > 0 && (
|
||||||
<div className="mt-3 p-3 bg-gray-800/30 rounded-lg">
|
<div className="mt-3 p-3 bg-gray-800/30 rounded-lg">
|
||||||
<div className="text-xs text-gray-400">
|
<div className="text-xs text-gray-400">
|
||||||
Selected layouts: <span className="text-cyan-400">{selectedLayouts.join(', ')}</span>
|
Selected layouts: <span className="text-cyan-400">
|
||||||
|
{selectedLayouts.map(layout => getLayoutDisplayName(layout)).join(', ')}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@@ -811,7 +839,7 @@ export default function AIAnalysisPanel({ onAnalysisComplete }: AIAnalysisPanelP
|
|||||||
<div>
|
<div>
|
||||||
<h4 className="text-cyan-400 font-medium text-lg">AI Analysis in Progress</h4>
|
<h4 className="text-cyan-400 font-medium text-lg">AI Analysis in Progress</h4>
|
||||||
<p className="text-cyan-300 text-sm opacity-90">
|
<p className="text-cyan-300 text-sm opacity-90">
|
||||||
Analyzing {symbol} • {selectedLayouts.join(', ')} layouts
|
Analyzing {symbol} • {selectedLayouts.map(layout => getLayoutDisplayName(layout)).join(', ')} layouts
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -17,7 +17,8 @@ export interface ScreenshotConfig {
|
|||||||
const LAYOUT_URLS = {
|
const LAYOUT_URLS = {
|
||||||
'ai': 'Z1TzpUrf',
|
'ai': 'Z1TzpUrf',
|
||||||
'diy': 'vWVvjLhP',
|
'diy': 'vWVvjLhP',
|
||||||
'Diy module': 'vWVvjLhP' // Alternative mapping for 'Diy module'
|
'Diy module': 'vWVvjLhP', // Exact TradingView name
|
||||||
|
'diy module': 'vWVvjLhP' // Lowercase fallback
|
||||||
}
|
}
|
||||||
|
|
||||||
export class EnhancedScreenshotService {
|
export class EnhancedScreenshotService {
|
||||||
|
|||||||
Reference in New Issue
Block a user