feat: update timeframe presets and improve sorting

- Add 30m and 2h timeframes to available options
- Update Scalping preset: 5m, 15m, 30m (was 5m, 15m, 1h)
- Update Day Trading preset: 1h, 2h, 4h (was 1h, 4h, 1d)
- Enhance sorting logic for screenshots and analysis results
- Ensure consistent timeframe order: 5m → 15m → 30m → 1h → 2h → 4h → 1d
- Improve multi-timeframe analysis display with proper sorting
- Update filename parsing to handle new timeframes

Changes improve trading workflow with more logical timeframe progressions
for scalping and day trading strategies.
This commit is contained in:
mindesbunister
2025-07-17 11:25:11 +02:00
parent ff4e9737fb
commit 4f328fab48
2 changed files with 116 additions and 34 deletions

View File

@@ -34,6 +34,56 @@ export default function ScreenshotGallery({
if (screenshots.length === 0) return null
// Utility function to convert timeframe to sortable number
const timeframeToMinutes = (timeframe: string): number => {
const tf = timeframe.toLowerCase()
if (tf.includes('5m') || tf === '5') return 5
if (tf.includes('15m') || tf === '15') return 15
if (tf.includes('30m') || tf === '30') return 30
if (tf.includes('1h') || tf === '60') return 60
if (tf.includes('2h') || tf === '120') return 120
if (tf.includes('4h') || tf === '240') return 240
if (tf.includes('1d') || tf === 'D') return 1440
// Default fallback
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]
if (tf === 'D') return '1D'
if (tf === '5') return '5m'
if (tf === '15') return '15m'
if (tf === '30') return '30m'
if (tf === '60') return '1h'
if (tf === '120') return '2h'
if (tf === '240') return '4h'
return `${tf}m`
}
// Create sorted screenshot data with timeframes
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)
return {
screenshot,
screenshotUrl,
filename,
timeframe,
index,
sortOrder: timeframeToMinutes(timeframe)
}
})
// Sort by timeframe (smallest to largest)
const sortedData = screenshotData.sort((a, b) => a.sortOrder - b.sortOrder)
// Helper function to format screenshot URL
const formatScreenshotUrl = (screenshot: string | any) => {
// Handle both string URLs and screenshot objects
@@ -56,36 +106,17 @@ export default function ScreenshotGallery({
Chart Screenshots
</h4>
<div className="text-xs text-gray-400">
{screenshots.length} captured Click to enlarge
{sortedData.length} captured Click to enlarge
</div>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{screenshots.map((screenshot, index) => {
// Handle both string URLs and screenshot objects
const screenshotUrl = typeof screenshot === 'string'
? screenshot
: (screenshot as any)?.url || String(screenshot)
const filename = screenshotUrl.split('/').pop() || ''
// 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)
{sortedData.map((item, displayIndex) => {
const imageUrl = formatScreenshotUrl(item.screenshot)
return (
<div
key={index}
key={displayIndex}
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(imageUrl)}
>
@@ -93,7 +124,7 @@ export default function ScreenshotGallery({
<div className="aspect-video bg-gray-800 flex items-center justify-center relative">
<img
src={imageUrl}
alt={`${symbol} - ${timeframe} chart`}
alt={`${symbol} - ${item.timeframe} chart`}
className="w-full h-full object-cover"
onError={(e: any) => {
const target = e.target as HTMLImageElement
@@ -106,7 +137,7 @@ export default function ScreenshotGallery({
<div className="text-center">
<div className="text-3xl mb-2">📊</div>
<div className="text-sm">Chart Preview</div>
<div className="text-xs text-gray-500">{filename}</div>
<div className="text-xs text-gray-500">{item.filename}</div>
</div>
</div>
@@ -125,7 +156,7 @@ 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">{timeframe} Timeframe</div>
<div className="text-xs text-purple-300">{item.timeframe} Timeframe</div>
</div>
<div className="text-xs text-gray-400">
Click to view