Fix screenshot gallery layout and timeframe descriptions
- Extract both layout and timeframe information from filenames - Group screenshots by layout (AI Layout, DIY Module) - Sort timeframes within each layout group ascending (5m -> 4h) - Display proper layout names and timeframes in descriptions - Organize display as: first layout ascending, then second layout ascending - Improve screenshot alt text with layout and timeframe info Screenshots now properly show: Top row: AI Layout (5m, 15m, 30m) Bottom row: DIY Module (5m, 15m, 30m)
This commit is contained in:
@@ -48,11 +48,29 @@ export default function ScreenshotGallery({
|
||||
return parseInt(tf) || 999
|
||||
}
|
||||
|
||||
// Extract timeframe from filename
|
||||
const extractTimeframeFromFilename = (filename: string) => {
|
||||
const match = filename.match(/_(\d+|D)_/)
|
||||
if (!match) return 'Unknown'
|
||||
const tf = match[1]
|
||||
// Extract layout and timeframe from filename
|
||||
const extractInfoFromFilename = (filename: string) => {
|
||||
// Pattern: SYMBOL_TIMEFRAME_LAYOUT_TIMESTAMP.png
|
||||
// e.g., SOLUSD_5_ai_1752749431435.png or SOLUSD_15_Diy module_1752749479893.png
|
||||
const parts = filename.replace('.png', '').split('_')
|
||||
if (parts.length >= 4) {
|
||||
const timeframe = parts[1]
|
||||
const layout = parts.slice(2, -1).join('_') // Handle "Diy module" with space
|
||||
return { timeframe, layout }
|
||||
}
|
||||
|
||||
// Fallback: try to extract from anywhere in filename
|
||||
const timeframeMatch = filename.match(/_(\d+|D)_/)
|
||||
const layoutMatch = filename.match(/_(ai|Diy module|diy)_/)
|
||||
|
||||
return {
|
||||
timeframe: timeframeMatch ? timeframeMatch[1] : 'Unknown',
|
||||
layout: layoutMatch ? layoutMatch[1] : 'Unknown'
|
||||
}
|
||||
}
|
||||
|
||||
// Format timeframe for display
|
||||
const formatTimeframe = (tf: string): string => {
|
||||
if (tf === 'D') return '1D'
|
||||
if (tf === '5') return '5m'
|
||||
if (tf === '15') return '15m'
|
||||
@@ -63,26 +81,61 @@ export default function ScreenshotGallery({
|
||||
return `${tf}m`
|
||||
}
|
||||
|
||||
// Create sorted screenshot data with timeframes
|
||||
// Format layout name for display
|
||||
const formatLayoutName = (layout: string): string => {
|
||||
if (layout === 'ai') return 'AI Layout'
|
||||
if (layout === 'Diy module') return 'DIY Module'
|
||||
return layout
|
||||
}
|
||||
|
||||
// Create screenshot data with extracted info
|
||||
const screenshotData = screenshots.map((screenshot, index) => {
|
||||
const screenshotUrl = typeof screenshot === 'string'
|
||||
? screenshot
|
||||
: (screenshot as any)?.url || String(screenshot)
|
||||
const filename = screenshotUrl.split('/').pop() || ''
|
||||
const timeframe = timeframes[index] || extractTimeframeFromFilename(filename)
|
||||
const { timeframe, layout } = extractInfoFromFilename(filename)
|
||||
|
||||
return {
|
||||
screenshot,
|
||||
screenshotUrl,
|
||||
filename,
|
||||
timeframe,
|
||||
layout,
|
||||
displayTimeframe: formatTimeframe(timeframe),
|
||||
displayLayout: formatLayoutName(layout),
|
||||
index,
|
||||
sortOrder: timeframeToMinutes(timeframe)
|
||||
sortOrder: timeframeToMinutes(formatTimeframe(timeframe))
|
||||
}
|
||||
})
|
||||
|
||||
// Sort by timeframe (smallest to largest)
|
||||
const sortedData = screenshotData.sort((a, b) => a.sortOrder - b.sortOrder)
|
||||
// Group by layout and sort within each group
|
||||
const groupedData = screenshotData.reduce((acc: any, item) => {
|
||||
if (!acc[item.layout]) {
|
||||
acc[item.layout] = []
|
||||
}
|
||||
acc[item.layout].push(item)
|
||||
return acc
|
||||
}, {})
|
||||
|
||||
// Sort each layout group by timeframe and combine
|
||||
// First layout (ai), then second layout (Diy module)
|
||||
const layoutOrder = ['ai', 'Diy module']
|
||||
const sortedData = layoutOrder.reduce((result: any[], layoutKey) => {
|
||||
if (groupedData[layoutKey]) {
|
||||
const sortedGroup = groupedData[layoutKey].sort((a: any, b: any) => a.sortOrder - b.sortOrder)
|
||||
result.push(...sortedGroup)
|
||||
}
|
||||
return result
|
||||
}, [])
|
||||
|
||||
// Add any remaining layouts not in the predefined order
|
||||
Object.keys(groupedData).forEach(layoutKey => {
|
||||
if (!layoutOrder.includes(layoutKey)) {
|
||||
const sortedGroup = groupedData[layoutKey].sort((a: any, b: any) => a.sortOrder - b.sortOrder)
|
||||
sortedData.push(...sortedGroup)
|
||||
}
|
||||
})
|
||||
|
||||
// Helper function to format screenshot URL
|
||||
const formatScreenshotUrl = (screenshot: string | any) => {
|
||||
@@ -124,7 +177,7 @@ export default function ScreenshotGallery({
|
||||
<div className="aspect-video bg-gray-800 flex items-center justify-center relative">
|
||||
<img
|
||||
src={imageUrl}
|
||||
alt={`${symbol} - ${item.timeframe} chart`}
|
||||
alt={`${symbol} - ${item.displayLayout} - ${item.displayTimeframe} chart`}
|
||||
className="w-full h-full object-cover"
|
||||
onError={(e: any) => {
|
||||
const target = e.target as HTMLImageElement
|
||||
@@ -156,7 +209,8 @@ export default function ScreenshotGallery({
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<div className="text-sm font-medium text-white">{symbol}</div>
|
||||
<div className="text-xs text-purple-300">{item.timeframe} Timeframe</div>
|
||||
<div className="text-xs text-purple-300">{item.displayLayout}</div>
|
||||
<div className="text-xs text-gray-400">{item.displayTimeframe} Timeframe</div>
|
||||
</div>
|
||||
<div className="text-xs text-gray-400">
|
||||
Click to view
|
||||
|
||||
Reference in New Issue
Block a user