diff --git a/src/components/UnifiedAnalysis.css b/src/components/UnifiedAnalysis.css index a5fed4c..3d48af8 100644 --- a/src/components/UnifiedAnalysis.css +++ b/src/components/UnifiedAnalysis.css @@ -1432,4 +1432,160 @@ padding: 10px 12px; font-size: 13px; } +} + +/* Hookpilot Status Modal */ +.hookpilot-modal-overlay { + z-index: 10000; +} + +.hookpilot-modal-content { + max-width: 500px; + text-align: center; +} + +.hookpilot-modal-header { + padding: 32px 24px 24px; + border-bottom: 1px solid #e2e8f0; +} + +.hookpilot-modal-header h3 { + margin: 0; + font-size: 24px; + font-weight: 700; + color: #1e293b; +} + +.hookpilot-modal-body { + padding: 32px 24px; +} + +.hookpilot-message { + font-size: 16px; + color: #475569; + margin: 0 0 16px 0; + line-height: 1.6; +} + +.hookpilot-error-details { + background: #fef2f2; + border: 1px solid #fecaca; + border-radius: 8px; + padding: 16px; + margin: 16px 0; +} + +.hookpilot-error-details p { + margin: 0; + color: #dc2626; + font-size: 14px; + line-height: 1.5; + font-family: 'Courier New', monospace; +} + +.hookpilot-subtext { + font-size: 14px; + color: #64748b; + margin: 16px 0 0 0; + font-style: italic; +} + +.hookpilot-spinner { + margin: 24px auto; + width: 48px; + height: 48px; + border: 4px solid #e2e8f0; + border-top: 4px solid #3b82f6; + border-radius: 50%; + animation: hookpilot-spin 0.8s linear infinite; +} + +@keyframes hookpilot-spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} + +.hookpilot-modal-actions { + margin-top: 24px; + display: flex; + justify-content: center; + gap: 12px; +} + +.hookpilot-modal-btn { + padding: 12px 32px; + font-size: 15px; + font-weight: 600; + border: none; + border-radius: 8px; + cursor: pointer; + transition: all 0.2s ease; + background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%); + color: white; + box-shadow: 0 2px 4px rgba(59, 130, 246, 0.2); +} + +.hookpilot-modal-btn:hover { + transform: translateY(-1px); + box-shadow: 0 4px 8px rgba(59, 130, 246, 0.3); +} + +.hookpilot-modal-btn:active { + transform: translateY(0); +} + +/* Success state styling */ +.hookpilot-modal-content.hookpilot-success .hookpilot-modal-header { + background: linear-gradient(135deg, #ecfdf5 0%, #d1fae5 100%); + border-bottom: 2px solid #10b981; +} + +.hookpilot-modal-content.hookpilot-success .hookpilot-modal-header h3 { + color: #065f46; +} + +/* Error state styling */ +.hookpilot-modal-content.hookpilot-error .hookpilot-modal-header { + background: linear-gradient(135deg, #fef2f2 0%, #fee2e2 100%); + border-bottom: 2px solid #ef4444; +} + +.hookpilot-modal-content.hookpilot-error .hookpilot-modal-header h3 { + color: #991b1b; +} + +/* Warning state styling */ +.hookpilot-modal-content.hookpilot-warning .hookpilot-modal-header { + background: linear-gradient(135deg, #fffbeb 0%, #fef3c7 100%); + border-bottom: 2px solid #f59e0b; +} + +.hookpilot-modal-content.hookpilot-warning .hookpilot-modal-header h3 { + color: #92400e; +} + +/* Sending state styling */ +.hookpilot-modal-content.hookpilot-sending .hookpilot-modal-header { + background: linear-gradient(135deg, #eff6ff 0%, #dbeafe 100%); + border-bottom: 2px solid #3b82f6; +} + +.hookpilot-modal-content.hookpilot-sending .hookpilot-modal-header h3 { + color: #1e40af; +} + +/* Responsive adjustments */ +@media (max-width: 600px) { + .hookpilot-modal-content { + max-width: 90%; + margin: 20px; + } + + .hookpilot-modal-header h3 { + font-size: 20px; + } + + .hookpilot-message { + font-size: 15px; + } } \ No newline at end of file diff --git a/src/components/UnifiedAnalysis.jsx b/src/components/UnifiedAnalysis.jsx index 1bd7d02..94d4be8 100644 --- a/src/components/UnifiedAnalysis.jsx +++ b/src/components/UnifiedAnalysis.jsx @@ -10,6 +10,7 @@ function UnifiedAnalysis({ analysisData }) { const [currentPage, setCurrentPage] = useState(1) const [itemsPerPage, setItemsPerPage] = useState(25) const [selectedDomain, setSelectedDomain] = useState(null) // Track which domain modal is open + const [hookpilotModal, setHookpilotModal] = useState({ show: false, status: 'sending', message: '', error: '' }) // Hookpilot status modal if (!analysisData) return null @@ -31,8 +32,13 @@ function UnifiedAnalysis({ analysisData }) { const hasKeywordOpportunities = informationalGapKeywords.length > 0 const handleSendToHookpilot = async () => { - // Initial alert to inform user - alert('⏳ Sending data to Hookpilot...\n\nYou will be notified once the operation completes or if any issues occur.') + // Show sending modal + setHookpilotModal({ + show: true, + status: 'sending', + message: 'Sending data to Hookpilot...', + error: '' + }) setSending(true) setHookpilotStatus(null) @@ -41,22 +47,41 @@ function UnifiedAnalysis({ analysisData }) { const result = await sendToHookpilot(analysisData) setHookpilotStatus(result) - // Success alert + // Show success or warning modal if (result.success) { - alert('✅ Success!\n\nData has been successfully sent to Hookpilot.') + setHookpilotModal({ + show: true, + status: 'success', + message: 'Data has been successfully sent to Hookpilot!', + error: '' + }) } else { - alert('⚠️ Warning!\n\nData was sent but Hookpilot returned an unexpected response. Please check the status below.') + setHookpilotModal({ + show: true, + status: 'warning', + message: 'Data was sent but Hookpilot returned an unexpected response.', + error: 'Please check the status below for more details.' + }) } } catch (error) { setHookpilotStatus({ success: false, error: error.message }) - // Error alert - alert(`❌ Error!\n\nFailed to send data to Hookpilot:\n\n${error.message}`) + // Show error modal + setHookpilotModal({ + show: true, + status: 'error', + message: 'Failed to send data to Hookpilot', + error: error.message + }) } finally { setSending(false) } } + const closeHookpilotModal = useCallback(() => { + setHookpilotModal({ show: false, status: '', message: '', error: '' }) + }, []) + // Use gap keywords directly (no tabs needed) const currentKeywords = informationalGapKeywords @@ -712,6 +737,72 @@ function UnifiedAnalysis({ analysisData }) { )} + + {/* Hookpilot Status Modal */} + {hookpilotModal.show && ( +
{hookpilotModal.message}
+ {hookpilotModal.error && ( +{hookpilotModal.error}
++ You will be notified once the operation completes or if any issues occur. +
+ )} + + {hookpilotModal.status !== 'sending' && ( +