diff --git a/cannaiq/src/pages/WorkersDashboard.tsx b/cannaiq/src/pages/WorkersDashboard.tsx index 972fbc5c..3e34a624 100644 --- a/cannaiq/src/pages/WorkersDashboard.tsx +++ b/cannaiq/src/pages/WorkersDashboard.tsx @@ -688,21 +688,41 @@ function WorkerSlot({ const maxTasks = worker?.max_concurrent_tasks || 3; const isOverloaded = (worker?.active_task_count || 0) >= maxTasks; - // Build fingerprint tooltip + // Build fingerprint tooltip - use actual API field names + const fp = fingerprint as any; // API returns different shape than interface const fingerprintTooltip = [ - '=== FINGERPRINT ===', - fingerprint?.browser ? `Browser: ${fingerprint.browser}` : 'Browser: Unknown', - fingerprint?.platform ? `Platform: ${fingerprint.platform}` : '', - fingerprint?.timezone ? `Timezone: ${fingerprint.timezone}` : '', + '═══ FINGERPRINT ═══', + fp?.browserName ? `Browser: ${fp.browserName}` : 'Browser: Unknown', + fp?.deviceCategory ? `Device: ${fp.deviceCategory}` : '', + fp?.userAgent ? `UA: ${fp.userAgent.slice(0, 50)}...` : '', '', - '=== BOT DETECTION ===', - fingerprint?.botDetection ? `Webdriver: ${fingerprint.botDetection.webdriver ? '⚠️ DETECTED' : '✓ Hidden'}` : '', - fingerprint?.botDetection ? `Automation: ${fingerprint.botDetection.automationControlled ? '⚠️ DETECTED' : '✓ Hidden'}` : '', + '═══ LOCATION ═══', + fp?.detectedLocation?.city ? `City: ${fp.detectedLocation.city}` : '', + fp?.detectedLocation?.region ? `State: ${fp.detectedLocation.region}` : '', + fp?.detectedTimezone ? `Timezone: ${fp.detectedTimezone}` : '', '', - '=== PRODUCTS ===', - fingerprint?.productsReturned !== undefined ? `Products returned: ${fingerprint.productsReturned}` : '', + '═══ PROXY ═══', + httpIp ? `IP: ${httpIp}` : '', + fp?.productsReturned !== undefined ? `Test Products: ${fp.productsReturned}` : '', ].filter(Boolean).join('\n'); + // Preflight status helpers + const httpStatus = worker?.preflight_http_status; + const curlStatus = worker?.preflight_curl_status; + + const getStatusIcon = (status: string | undefined, label: string) => { + if (status === 'passed') return ; + if (status === 'failed') return ; + if (status === 'skipped') return ; + return ; + }; + + const getStatusColor = (status: string | undefined) => { + if (status === 'passed') return 'text-emerald-600'; + if (status === 'failed') return 'text-red-600'; + return 'text-yellow-600'; + }; + // Slot is idle (no task) if (!task) { // Show preflight checklist if not yet qualified @@ -713,34 +733,39 @@ function WorkerSlot({ onMouseEnter={() => setIsHovered(true)} onMouseLeave={() => setIsHovered(false)} > -
Slot {slotIndex + 1}
+
Slot {slotIndex + 1} - Starting
+ {/* HTTP Preflight */}
- {isOverloaded ? ( - - ) : ( - - )} - Overload? + {getStatusIcon(httpStatus, 'HTTP')} + + HTTP Preflight {httpStatus === 'passed' ? '✓' : httpStatus === 'failed' ? '✗' : '...'} +
+ {/* Geo Session */}
- {isDecommissioning ? ( - - ) : ( + {hasGeo ? ( + ) : httpStatus === 'passed' ? ( + + ) : ( + )} - Terminating? + + Geo Session {hasGeo ? '✓' : httpStatus === 'passed' ? '...' : ''} +
+ {/* Pool Ready */}
- {!poolOpen ? ( - + {isQualified ? ( + ) : hasGeo ? ( - + ) : ( - + )} - - Pool Query? + + Pool Ready {isQualified ? '✓' : hasGeo ? '...' : ''}