ALwrity version 0.5.5
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import {
|
||||
Box,
|
||||
Paper,
|
||||
@@ -59,6 +59,7 @@ import StrategicInputField from './ContentStrategyBuilder/StrategicInputField';
|
||||
import EnhancedTooltip from './ContentStrategyBuilder/EnhancedTooltip';
|
||||
import AIRecommendationsPanel from './AIRecommendationsPanel';
|
||||
import DataSourceTransparency from './DataSourceTransparency';
|
||||
import StrategyAutofillTransparencyModal from './StrategyAutofillTransparencyModal';
|
||||
|
||||
// Import extracted hooks
|
||||
import { useCategoryReview } from './ContentStrategyBuilder/hooks/useCategoryReview';
|
||||
@@ -97,6 +98,20 @@ const ContentStrategyBuilder: React.FC = () => {
|
||||
disclosureSteps,
|
||||
currentStrategy,
|
||||
updateFormField,
|
||||
// Transparency state
|
||||
transparencyModalOpen,
|
||||
generationProgress: storeGenerationProgress,
|
||||
currentPhase,
|
||||
educationalContent: storeEducationalContent,
|
||||
transparencyMessages,
|
||||
isGenerating,
|
||||
setTransparencyModalOpen,
|
||||
setGenerationProgress: setStoreGenerationProgress,
|
||||
setCurrentPhase,
|
||||
setEducationalContent: setStoreEducationalContent,
|
||||
addTransparencyMessage,
|
||||
clearTransparencyMessages,
|
||||
setIsGenerating,
|
||||
validateFormField,
|
||||
validateAllFields,
|
||||
completeStep,
|
||||
@@ -127,8 +142,8 @@ const ContentStrategyBuilder: React.FC = () => {
|
||||
const [isRefreshing, setIsRefreshing] = useState<boolean>(false);
|
||||
const [refreshError, setRefreshError] = useState<string | null>(null);
|
||||
const [showEducationalModal, setShowEducationalModal] = useState(false);
|
||||
const [educationalContent, setEducationalContent] = useState<any>(null);
|
||||
const [generationProgress, setGenerationProgress] = useState<number>(0);
|
||||
const [localEducationalContent, setLocalEducationalContent] = useState<any>(null);
|
||||
const [localGenerationProgress, setLocalGenerationProgress] = useState<number>(0);
|
||||
const [showAIRecModal, setShowAIRecModal] = useState(false);
|
||||
|
||||
// Ref to track if we've already set the default category
|
||||
@@ -171,8 +186,8 @@ const ContentStrategyBuilder: React.FC = () => {
|
||||
setError,
|
||||
setCurrentStrategy,
|
||||
setSaving,
|
||||
setGenerationProgress,
|
||||
setEducationalContent,
|
||||
setGenerationProgress: setStoreGenerationProgress,
|
||||
setEducationalContent: setStoreEducationalContent,
|
||||
setShowEducationalModal,
|
||||
validateAllFields,
|
||||
getCompletionStats,
|
||||
@@ -211,6 +226,21 @@ const ContentStrategyBuilder: React.FC = () => {
|
||||
console.trace('📍 Stack trace for activeCategory change');
|
||||
}, [activeCategory]);
|
||||
|
||||
// Monitor modal state for debugging
|
||||
useEffect(() => {
|
||||
console.log('🎯 Modal state changed - transparencyModalOpen:', transparencyModalOpen);
|
||||
}, [transparencyModalOpen]);
|
||||
|
||||
// Monitor store data changes for debugging
|
||||
useEffect(() => {
|
||||
console.log('🎯 Store data changed:', {
|
||||
autoPopulatedFieldsCount: Object.keys(autoPopulatedFields || {}).length,
|
||||
dataSourcesCount: Object.keys(dataSources || {}).length,
|
||||
inputDataPointsCount: Object.keys(inputDataPoints || {}).length,
|
||||
transparencyMessagesCount: transparencyMessages?.length || 0
|
||||
});
|
||||
}, [autoPopulatedFields, dataSources, inputDataPoints, transparencyMessages]);
|
||||
|
||||
// Add CSS keyframes for pulse animation
|
||||
useEffect(() => {
|
||||
const style = document.createElement('style');
|
||||
@@ -287,116 +317,207 @@ const ContentStrategyBuilder: React.FC = () => {
|
||||
onRefreshData={() => autoPopulateFromOnboarding()}
|
||||
onRefreshAI={async () => {
|
||||
try {
|
||||
// 🚀 POLLING-BASED AI REFRESH (No SSE)
|
||||
// We switched from SSE to polling for better reliability
|
||||
// This approach uses direct HTTP calls with visual feedback
|
||||
|
||||
// Open transparency modal and initialize transparency state
|
||||
console.log('🎯 Opening transparency modal...');
|
||||
setTransparencyModalOpen(true);
|
||||
setIsGenerating(true);
|
||||
setStoreGenerationProgress(0);
|
||||
setCurrentPhase('autofill_initialization');
|
||||
clearTransparencyMessages();
|
||||
addTransparencyMessage('Starting strategy inputs generation process...');
|
||||
console.log('🎯 Modal state set, transparency initialized');
|
||||
|
||||
setAIGenerating(true);
|
||||
setIsRefreshing(true);
|
||||
setRefreshError(null);
|
||||
setRefreshMessage('Initializing refresh…');
|
||||
setRefreshMessage('Initializing AI refresh…');
|
||||
setRefreshProgress(5);
|
||||
const es = await contentPlanningApi.streamAutofillRefresh(1, true, true);
|
||||
es.onmessage = (evt: MessageEvent) => {
|
||||
try {
|
||||
const data = JSON.parse(evt.data);
|
||||
if (data.type === 'status' || data.type === 'progress') {
|
||||
setRefreshMessage(data.message || 'Refreshing…');
|
||||
if (typeof data.progress === 'number') setRefreshProgress(data.progress);
|
||||
}
|
||||
if (data.type === 'result') {
|
||||
const payload = data.data || {};
|
||||
const fields = payload.fields || {};
|
||||
const sources = payload.sources || {};
|
||||
const inputDataPoints = payload.input_data_points || {};
|
||||
const meta = payload.meta || {};
|
||||
|
||||
console.log('🎯 AI Refresh Result - Payload:', payload);
|
||||
console.log('🎯 AI Refresh Result - Fields:', fields);
|
||||
console.log('🎯 AI Refresh Result - Meta:', meta);
|
||||
|
||||
const fieldValues: Record<string, any> = {};
|
||||
Object.keys(fields).forEach((fieldId) => {
|
||||
const fieldData = fields[fieldId];
|
||||
if (fieldData && typeof fieldData === 'object' && 'value' in fieldData) {
|
||||
fieldValues[fieldId] = fieldData.value;
|
||||
console.log(`✅ Processed field ${fieldId}:`, fieldData.value);
|
||||
} else {
|
||||
console.log(`❌ Skipped field ${fieldId}:`, fieldData);
|
||||
}
|
||||
});
|
||||
|
||||
console.log('🎯 Final fieldValues:', fieldValues);
|
||||
|
||||
useEnhancedStrategyStore.setState((state) => {
|
||||
const newState = {
|
||||
autoPopulatedFields: { ...state.autoPopulatedFields, ...fieldValues },
|
||||
dataSources: { ...state.dataSources, ...sources },
|
||||
inputDataPoints,
|
||||
formData: { ...state.formData, ...fieldValues }
|
||||
};
|
||||
console.log('🎯 Updated store state:', newState);
|
||||
return newState;
|
||||
});
|
||||
|
||||
// Enhanced success/error messaging based on retry attempts and success rate
|
||||
const attempts = meta.attempts || 1;
|
||||
const successRate = meta.success_rate || 0;
|
||||
const aiOverridesCount = meta.ai_overrides_count || 0;
|
||||
|
||||
if (!meta.ai_used || aiOverridesCount === 0) {
|
||||
const msg = meta.error || 'AI did not produce new values. Please try again or complete onboarding data.';
|
||||
setError(msg);
|
||||
setRefreshError(msg);
|
||||
setRefreshMessage(`No new AI values available. (${attempts} attempt${attempts > 1 ? 's' : ''})`);
|
||||
} else {
|
||||
// Show success message with retry info if applicable
|
||||
if (attempts > 1) {
|
||||
setRefreshMessage(`AI refresh completed successfully! Generated ${aiOverridesCount} fields in ${attempts} attempts (${successRate.toFixed(1)}% success rate).`);
|
||||
} else {
|
||||
setRefreshMessage(`AI refresh completed! Generated ${aiOverridesCount} fields (${successRate.toFixed(1)}% success rate).`);
|
||||
}
|
||||
|
||||
// Show warning if success rate is low but we got some data
|
||||
if (successRate < 70 && aiOverridesCount > 0) {
|
||||
setRefreshError(`Warning: Only ${successRate.toFixed(1)}% of fields were filled. Some fields may need manual input.`);
|
||||
}
|
||||
}
|
||||
|
||||
es.close();
|
||||
setAIGenerating(false);
|
||||
setIsRefreshing(false);
|
||||
|
||||
// Clear success message after a delay
|
||||
if (aiOverridesCount > 0) {
|
||||
setTimeout(() => {
|
||||
setRefreshMessage(null);
|
||||
setRefreshProgress(0);
|
||||
}, 5000);
|
||||
}
|
||||
}
|
||||
if (data.type === 'error') {
|
||||
const msg = data.message || 'AI refresh failed.';
|
||||
setRefreshError(msg);
|
||||
es.close();
|
||||
setAIGenerating(false);
|
||||
setIsRefreshing(false);
|
||||
setRefreshMessage('Refresh failed.');
|
||||
}
|
||||
} catch (err: any) {
|
||||
console.error('SSE parse error:', err);
|
||||
|
||||
// Start transparency message polling for visual feedback
|
||||
const transparencyMessages = [
|
||||
{ type: 'autofill_initialization', message: 'Starting strategy inputs generation process...', progress: 5 },
|
||||
{ type: 'autofill_data_collection', message: 'Collecting and analyzing data sources...', progress: 15 },
|
||||
{ type: 'autofill_data_quality', message: 'Assessing data quality and completeness...', progress: 25 },
|
||||
{ type: 'autofill_context_analysis', message: 'Analyzing business context and strategic framework...', progress: 35 },
|
||||
{ type: 'autofill_strategy_generation', message: 'Generating strategic insights and recommendations...', progress: 45 },
|
||||
{ type: 'autofill_field_generation', message: 'Generating individual strategy input fields...', progress: 55 },
|
||||
{ type: 'autofill_quality_validation', message: 'Validating generated strategy inputs...', progress: 65 },
|
||||
{ type: 'autofill_alignment_check', message: 'Checking strategy alignment and consistency...', progress: 75 },
|
||||
{ type: 'autofill_final_review', message: 'Performing final review and optimization...', progress: 85 },
|
||||
{ type: 'autofill_complete', message: 'Strategy inputs generation completed successfully...', progress: 95 }
|
||||
];
|
||||
|
||||
let messageIndex = 0;
|
||||
const transparencyInterval = setInterval(() => {
|
||||
if (messageIndex < transparencyMessages.length) {
|
||||
const message = transparencyMessages[messageIndex];
|
||||
console.log('🎯 Raw Polling Message:', {
|
||||
type: message.type,
|
||||
message: message.message,
|
||||
progress: message.progress,
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
setCurrentPhase(message.type);
|
||||
addTransparencyMessage(message.message);
|
||||
setStoreGenerationProgress(message.progress);
|
||||
setRefreshProgress(message.progress);
|
||||
messageIndex++;
|
||||
} else {
|
||||
clearInterval(transparencyInterval);
|
||||
}
|
||||
};
|
||||
es.onerror = (err: any) => {
|
||||
console.error('SSE connection error:', err);
|
||||
es.close();
|
||||
setAIGenerating(false);
|
||||
setIsRefreshing(false);
|
||||
setRefreshError('AI refresh connection lost. Please try again.');
|
||||
setRefreshMessage('Connection lost.');
|
||||
};
|
||||
}, 2000); // Send a message every 2 seconds for better UX
|
||||
|
||||
// Call the non-streaming refresh endpoint (Polling-based approach)
|
||||
console.log('🎯 Calling AI refresh endpoint (Polling-based)...');
|
||||
const response = await contentPlanningApi.refreshAutofill(1, true, true);
|
||||
console.log('🎯 Raw Polling Response:', {
|
||||
success: !!response,
|
||||
hasData: !!response?.data,
|
||||
responseStructure: {
|
||||
hasDataProperty: !!response?.data?.data,
|
||||
hasFieldsDirect: !!response?.data?.fields,
|
||||
hasFieldsInData: !!response?.data?.data?.fields
|
||||
},
|
||||
fieldsCount: Object.keys(response?.data?.data?.fields || response?.data?.fields || {}).length,
|
||||
sourcesCount: Object.keys(response?.data?.data?.sources || response?.data?.sources || {}).length,
|
||||
meta: response?.data?.data?.meta || response?.data?.meta || {},
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
|
||||
// Clear the transparency interval since we got the response
|
||||
clearInterval(transparencyInterval);
|
||||
|
||||
// Process the response
|
||||
if (response && response.data) {
|
||||
// The API response is wrapped in ResponseBuilder format:
|
||||
// { status: "success", message: "...", data: { fields: {...}, sources: {...}, meta: {...} } }
|
||||
// So we need to access payload.data.fields, not payload.fields
|
||||
const payload = response.data;
|
||||
const fields = payload.data?.fields || payload.fields || {};
|
||||
const sources = payload.data?.sources || payload.sources || {};
|
||||
const inputDataPoints = payload.data?.input_data_points || payload.input_data_points || {};
|
||||
const meta = payload.data?.meta || payload.meta || {};
|
||||
|
||||
console.log('🎯 AI Refresh Result - Payload:', payload);
|
||||
console.log('🎯 AI Refresh Result - Fields:', fields);
|
||||
console.log('🎯 AI Refresh Result - Meta:', meta);
|
||||
console.log('🎯 Fields structure check:', {
|
||||
fieldsType: typeof fields,
|
||||
fieldsKeys: Object.keys(fields),
|
||||
sampleField: fields[Object.keys(fields)[0]],
|
||||
hasValueProperty: fields[Object.keys(fields)[0]]?.hasOwnProperty('value')
|
||||
});
|
||||
|
||||
// 🚨 CRITICAL: Check if AI generation failed
|
||||
if (meta.error || !meta.ai_used || meta.ai_overrides_count === 0) {
|
||||
console.error('❌ AI generation failed:', meta.error || 'No AI data generated');
|
||||
setError(`AI generation failed: ${meta.error || 'No real AI data was generated. Please try again.'}`);
|
||||
setTransparencyModalOpen(false);
|
||||
setAIGenerating(false);
|
||||
setIsRefreshing(false);
|
||||
setIsGenerating(false);
|
||||
setRefreshError('AI generation failed. Please try again.');
|
||||
setRefreshMessage('Refresh failed.');
|
||||
return;
|
||||
}
|
||||
|
||||
// 🚨 CRITICAL: Validate data source
|
||||
if (meta.data_source === 'ai_generation_failed' || meta.data_source === 'ai_generation_error' || meta.data_source === 'ai_disabled') {
|
||||
console.error('❌ Invalid data source:', meta.data_source);
|
||||
setError(`AI generation failed: ${meta.error || 'Invalid data source. Please try again.'}`);
|
||||
setTransparencyModalOpen(false);
|
||||
setAIGenerating(false);
|
||||
setIsRefreshing(false);
|
||||
setIsGenerating(false);
|
||||
setRefreshError('AI generation failed. Please try again.');
|
||||
setRefreshMessage('Refresh failed.');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('✅ AI generation successful - processing real AI data');
|
||||
|
||||
const fieldValues: Record<string, any> = {};
|
||||
const confidenceScores: Record<string, number> = {};
|
||||
|
||||
Object.keys(fields).forEach((fieldId) => {
|
||||
const fieldData = fields[fieldId];
|
||||
console.log(`🎯 Processing field ${fieldId}:`, fieldData);
|
||||
|
||||
if (fieldData && typeof fieldData === 'object' && 'value' in fieldData) {
|
||||
fieldValues[fieldId] = fieldData.value;
|
||||
console.log(`✅ Field ${fieldId} value extracted:`, fieldData.value);
|
||||
|
||||
// Extract confidence score if available
|
||||
if (fieldData.confidence) {
|
||||
confidenceScores[fieldId] = fieldData.confidence;
|
||||
console.log(`🎯 Field ${fieldId} confidence: ${fieldData.confidence}`);
|
||||
}
|
||||
|
||||
// Extract personalization data if available
|
||||
if (fieldData.personalization_data) {
|
||||
console.log(`🎯 Field ${fieldId} personalization:`, fieldData.personalization_data);
|
||||
}
|
||||
} else {
|
||||
console.warn(`⚠️ Field ${fieldId} has invalid structure:`, fieldData);
|
||||
}
|
||||
});
|
||||
|
||||
console.log('🎯 Processed field values:', Object.keys(fieldValues));
|
||||
console.log('🎯 Confidence scores:', confidenceScores);
|
||||
console.log('🎯 Field values details:', fieldValues);
|
||||
|
||||
// Update the store with the new data
|
||||
useEnhancedStrategyStore.setState((state) => {
|
||||
const newState = {
|
||||
autoPopulatedFields: { ...state.autoPopulatedFields, ...fieldValues },
|
||||
dataSources: { ...state.dataSources, ...sources },
|
||||
inputDataPoints: { ...state.inputDataPoints, ...inputDataPoints },
|
||||
confidenceScores: { ...state.confidenceScores, ...confidenceScores },
|
||||
formData: { ...state.formData, ...fieldValues }
|
||||
};
|
||||
console.log('🎯 Updated store state:', newState);
|
||||
console.log('🎯 Field values being added:', fieldValues);
|
||||
console.log('🎯 Confidence scores being added:', confidenceScores);
|
||||
console.log('🎯 Store autoPopulatedFields count:', Object.keys(newState.autoPopulatedFields).length);
|
||||
return newState;
|
||||
});
|
||||
|
||||
// Add final completion message
|
||||
addTransparencyMessage(`✅ AI generation completed successfully! Generated ${Object.keys(fieldValues).length} real AI values.`);
|
||||
setStoreGenerationProgress(100);
|
||||
setRefreshProgress(100);
|
||||
setCurrentPhase('Complete');
|
||||
setRefreshMessage(`AI refresh completed! Generated ${Object.keys(fieldValues).length} fields.`);
|
||||
|
||||
// Close modal after a short delay to show completion
|
||||
setTimeout(() => {
|
||||
setTransparencyModalOpen(false);
|
||||
setAIGenerating(false);
|
||||
setIsRefreshing(false);
|
||||
setIsGenerating(false);
|
||||
console.log('🎯 Polling-based AI refresh completed successfully!', {
|
||||
fieldsGenerated: Object.keys(fieldValues).length,
|
||||
confidenceScoresCount: Object.keys(confidenceScores).length,
|
||||
dataSourcesCount: Object.keys(sources).length,
|
||||
approach: 'Polling (No SSE)',
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
}, 2000);
|
||||
} else {
|
||||
throw new Error('Invalid response from AI refresh endpoint');
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('AI refresh error', e);
|
||||
setAIGenerating(false);
|
||||
setIsRefreshing(false);
|
||||
setIsGenerating(false);
|
||||
setRefreshError('AI refresh failed. Please try again.');
|
||||
setRefreshMessage('Refresh failed.');
|
||||
setError(`AI refresh failed: ${e instanceof Error ? e.message : 'Unknown error'}`);
|
||||
}
|
||||
}}
|
||||
refreshMessage={refreshMessage}
|
||||
@@ -469,6 +590,7 @@ const ContentStrategyBuilder: React.FC = () => {
|
||||
formErrors={formErrors}
|
||||
autoPopulatedFields={autoPopulatedFields}
|
||||
dataSources={dataSources}
|
||||
inputDataPoints={inputDataPoints}
|
||||
personalizationData={personalizationData}
|
||||
completionStats={completionStats}
|
||||
reviewedCategories={reviewedCategories}
|
||||
@@ -478,7 +600,17 @@ const ContentStrategyBuilder: React.FC = () => {
|
||||
onUpdateFormField={updateFormField}
|
||||
onValidateFormField={validateFormField}
|
||||
onShowTooltip={setShowTooltip}
|
||||
onViewDataSource={() => setShowDataSourceTransparency(true)}
|
||||
onViewDataSource={(fieldId) => {
|
||||
// If a specific field is provided, show field-specific data source info
|
||||
if (fieldId) {
|
||||
console.log('🎯 Viewing data source for field:', fieldId);
|
||||
// For now, just open the general data source transparency modal
|
||||
// In the future, this could open a field-specific modal
|
||||
setShowDataSourceTransparency(true);
|
||||
} else {
|
||||
setShowDataSourceTransparency(true);
|
||||
}
|
||||
}}
|
||||
onConfirmCategoryReview={handleConfirmCategoryReviewWrapper}
|
||||
onSetActiveCategory={setActiveCategory}
|
||||
onSetShowEducationalInfo={setShowEducationalInfo}
|
||||
@@ -524,8 +656,8 @@ const ContentStrategyBuilder: React.FC = () => {
|
||||
<EducationalModal
|
||||
open={showEducationalModal}
|
||||
onClose={() => setShowEducationalModal(false)}
|
||||
educationalContent={educationalContent}
|
||||
generationProgress={generationProgress}
|
||||
educationalContent={storeEducationalContent}
|
||||
generationProgress={storeGenerationProgress}
|
||||
/>
|
||||
|
||||
{/* Data Source Transparency Modal */}
|
||||
@@ -555,6 +687,21 @@ const ContentStrategyBuilder: React.FC = () => {
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
|
||||
{/* Strategy Autofill Transparency Modal */}
|
||||
<StrategyAutofillTransparencyModal
|
||||
open={transparencyModalOpen}
|
||||
onClose={() => setTransparencyModalOpen(false)}
|
||||
autoPopulatedFields={autoPopulatedFields}
|
||||
dataSources={dataSources}
|
||||
inputDataPoints={inputDataPoints}
|
||||
isGenerating={isGenerating}
|
||||
generationProgress={storeGenerationProgress}
|
||||
currentPhase={currentPhase}
|
||||
educationalContent={storeEducationalContent}
|
||||
transparencyMessages={transparencyMessages}
|
||||
error={error}
|
||||
/>
|
||||
|
||||
{/* Tooltip */}
|
||||
{showTooltip && (
|
||||
<EnhancedTooltip
|
||||
|
||||
@@ -25,6 +25,7 @@ import {
|
||||
import { motion } from 'framer-motion';
|
||||
import StrategicInputField from '../StrategicInputField';
|
||||
import { CategoryDetailViewProps, EducationalInfoDialogProps } from '../types/contentStrategy.types';
|
||||
import { useEnhancedStrategyStore } from '../../../../../stores/enhancedStrategyStore';
|
||||
|
||||
const EducationalInfoDialog: React.FC<EducationalInfoDialogProps> = ({
|
||||
open,
|
||||
@@ -97,6 +98,7 @@ const CategoryDetailView: React.FC<CategoryDetailViewProps> = ({
|
||||
formErrors,
|
||||
autoPopulatedFields,
|
||||
dataSources,
|
||||
inputDataPoints,
|
||||
personalizationData,
|
||||
completionStats,
|
||||
reviewedCategories,
|
||||
@@ -114,6 +116,8 @@ const CategoryDetailView: React.FC<CategoryDetailViewProps> = ({
|
||||
getCategoryColor,
|
||||
getEducationalContent
|
||||
}) => {
|
||||
// Get confidence scores from store
|
||||
const { confidenceScores } = useEnhancedStrategyStore();
|
||||
if (!activeCategory) {
|
||||
return (
|
||||
<motion.div
|
||||
@@ -193,13 +197,13 @@ const CategoryDetailView: React.FC<CategoryDetailViewProps> = ({
|
||||
error={formErrors[field.id]}
|
||||
autoPopulated={!!autoPopulatedFields[field.id]}
|
||||
dataSource={dataSources[field.id]}
|
||||
confidenceLevel={autoPopulatedFields[field.id] ? 0.8 : undefined}
|
||||
confidenceLevel={confidenceScores[field.id] || (autoPopulatedFields[field.id] ? 0.8 : undefined)}
|
||||
dataQuality={autoPopulatedFields[field.id] ? 'High Quality' : undefined}
|
||||
personalizationData={personalizationData[field.id]}
|
||||
onChange={(value: any) => onUpdateFormField(field.id, value)}
|
||||
onValidate={() => onValidateFormField(field.id)}
|
||||
onShowTooltip={() => onShowTooltip(field.id)}
|
||||
onViewDataSource={onViewDataSource}
|
||||
onViewDataSource={() => onViewDataSource(field.id)}
|
||||
accentColorKey={getCategoryColor(activeCategory) as any}
|
||||
isCompact={isCompactField}
|
||||
/>
|
||||
|
||||
@@ -26,6 +26,7 @@ export interface CategoryDetailViewProps {
|
||||
formErrors: Record<string, any>;
|
||||
autoPopulatedFields: Record<string, any>;
|
||||
dataSources: Record<string, any>;
|
||||
inputDataPoints: Record<string, any>;
|
||||
personalizationData: Record<string, any>;
|
||||
completionStats: any;
|
||||
reviewedCategories: Set<string>;
|
||||
@@ -35,7 +36,7 @@ export interface CategoryDetailViewProps {
|
||||
onUpdateFormField: (fieldId: string, value: any) => void;
|
||||
onValidateFormField: (fieldId: string) => boolean;
|
||||
onShowTooltip: (fieldId: string) => void;
|
||||
onViewDataSource: () => void;
|
||||
onViewDataSource: (fieldId?: string) => void;
|
||||
onConfirmCategoryReview: () => void;
|
||||
onSetActiveCategory: (category: string | null) => void;
|
||||
onSetShowEducationalInfo: (categoryId: string | null) => void;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -539,222 +539,29 @@ class ContentPlanningAPI {
|
||||
}
|
||||
|
||||
// Enhanced Strategy API Methods
|
||||
async createEnhancedStrategy(strategy: any): Promise<any> {
|
||||
return this.handleRequest(async () => {
|
||||
const response = await apiClient.post(`${this.baseURL}/enhanced-strategies/create`, strategy);
|
||||
// Extract data from the response wrapper
|
||||
return response.data.data || response.data;
|
||||
});
|
||||
}
|
||||
|
||||
// SSE Strategy Generation
|
||||
async streamStrategyGeneration(strategyId: number): Promise<EventSource> {
|
||||
// The backend endpoint doesn't need strategy_id, it creates the strategy internally
|
||||
const url = `${this.baseURL}/content-strategy/ai-generation/generate-comprehensive-strategy/stream?user_id=1&strategy_name=Enhanced%20Content%20Strategy`;
|
||||
|
||||
console.log('🚀 Creating SSE connection for strategy generation:');
|
||||
console.log(' URL:', url);
|
||||
console.log(' Base URL:', this.baseURL);
|
||||
console.log(' Strategy ID:', strategyId);
|
||||
|
||||
const eventSource = new EventSource(url);
|
||||
|
||||
// Add comprehensive error handling
|
||||
eventSource.onerror = (error) => {
|
||||
console.error('❌ SSE Error in strategy generation:', error);
|
||||
console.error(' ReadyState:', eventSource.readyState);
|
||||
console.error(' URL:', url);
|
||||
|
||||
// Don't close immediately on error - let the frontend handle it
|
||||
// eventSource.close();
|
||||
};
|
||||
|
||||
eventSource.onopen = () => {
|
||||
console.log('✅ SSE connection opened successfully');
|
||||
console.log(' ReadyState:', eventSource.readyState);
|
||||
console.log(' URL:', url);
|
||||
};
|
||||
|
||||
eventSource.onmessage = (event) => {
|
||||
console.log('📨 SSE message received:', event.data);
|
||||
};
|
||||
|
||||
return eventSource;
|
||||
}
|
||||
|
||||
// New polling-based strategy generation methods
|
||||
async startStrategyGenerationPolling(userId: number = 1, strategyName?: string, config?: any): Promise<any> {
|
||||
return this.handleRequest(async () => {
|
||||
const payload = {
|
||||
user_id: userId,
|
||||
strategy_name: strategyName || 'Enhanced Content Strategy',
|
||||
config: config || {}
|
||||
};
|
||||
|
||||
console.log('🚀 Starting polling-based strategy generation:', payload);
|
||||
|
||||
const response = await apiClient.post(
|
||||
`${this.baseURL}/content-strategy/ai-generation/generate-comprehensive-strategy-polling`,
|
||||
payload
|
||||
);
|
||||
|
||||
console.log('✅ Strategy generation started:', response.data);
|
||||
return response.data.data || response.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getStrategyGenerationStatus(taskId: string): Promise<any> {
|
||||
return this.handleRequest(async () => {
|
||||
const response = await apiClient.get(`${this.baseURL}/content-strategy/ai-generation/strategy-generation-status/${taskId}`);
|
||||
return response.data.data || response.data;
|
||||
});
|
||||
}
|
||||
|
||||
// Get the latest generated strategy from polling system
|
||||
async getLatestGeneratedStrategy(userId: number = 1): Promise<any> {
|
||||
return this.handleRequest(async () => {
|
||||
const response = await apiClient.get(`${this.baseURL}/content-strategy/ai-generation/latest-strategy`, {
|
||||
params: { user_id: userId }
|
||||
});
|
||||
return response.data.data || response.data;
|
||||
});
|
||||
}
|
||||
|
||||
// Polling utility method
|
||||
async pollStrategyGeneration(
|
||||
taskId: string,
|
||||
onProgress: (status: any) => void,
|
||||
onComplete: (strategy: any) => void,
|
||||
onError: (error: any) => void,
|
||||
pollInterval: number = 10000, // 10 seconds
|
||||
maxAttempts: number = 36 // 6 minutes max (36 * 10 seconds)
|
||||
): Promise<void> {
|
||||
let attempts = 0;
|
||||
|
||||
const poll = async () => {
|
||||
try {
|
||||
attempts++;
|
||||
console.log(`📊 Polling attempt ${attempts}/${maxAttempts} for task: ${taskId}`);
|
||||
|
||||
const status = await this.getStrategyGenerationStatus(taskId);
|
||||
|
||||
// Call progress callback
|
||||
onProgress(status);
|
||||
|
||||
// Check if completed
|
||||
if (status.status === 'completed') {
|
||||
console.log('✅ Strategy generation completed:', status);
|
||||
onComplete(status.strategy);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if failed
|
||||
if (status.status === 'failed') {
|
||||
console.error('❌ Strategy generation failed:', status.error);
|
||||
onError(status.error || 'Strategy generation failed');
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if max attempts reached
|
||||
if (attempts >= maxAttempts) {
|
||||
console.warn('⏰ Max polling attempts reached, checking final status...');
|
||||
const finalStatus = await this.getStrategyGenerationStatus(taskId);
|
||||
|
||||
if (finalStatus.status === 'completed') {
|
||||
onComplete(finalStatus.strategy);
|
||||
} else {
|
||||
onError('Strategy generation timeout. The process may still be running in the background.');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Continue polling
|
||||
setTimeout(poll, pollInterval);
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Error polling strategy generation status:', error);
|
||||
onError(error);
|
||||
}
|
||||
};
|
||||
|
||||
// Start polling
|
||||
poll();
|
||||
}
|
||||
|
||||
async updateEnhancedStrategy(id: string, updates: any): Promise<any> {
|
||||
return this.handleRequest(async () => {
|
||||
const response = await apiClient.put(`${this.baseURL}/enhanced-strategies/${id}`, updates);
|
||||
return response.data.data || response.data;
|
||||
});
|
||||
}
|
||||
|
||||
async deleteEnhancedStrategy(id: string): Promise<any> {
|
||||
return this.handleRequest(async () => {
|
||||
const response = await apiClient.delete(`${this.baseURL}/enhanced-strategies/${id}`);
|
||||
return response.data.data || response.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getEnhancedStrategies(userId?: number): Promise<any> {
|
||||
return this.handleRequest(async () => {
|
||||
const params = userId ? { user_id: userId } : {};
|
||||
const params: any = {};
|
||||
if (userId) params.user_id = userId;
|
||||
const response = await apiClient.get(`${this.baseURL}/enhanced-strategies`, { params });
|
||||
return response.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getEnhancedStrategy(strategyId: string): Promise<any> {
|
||||
return this.handleRequest(async () => {
|
||||
const response = await apiClient.get(`${this.baseURL}/enhanced-strategies/${strategyId}`);
|
||||
return response.data;
|
||||
});
|
||||
}
|
||||
|
||||
async createEnhancedStrategy(strategy: any): Promise<any> {
|
||||
return this.handleRequest(async () => {
|
||||
const response = await apiClient.post(`${this.baseURL}/enhanced-strategies`, strategy);
|
||||
return response.data.data || response.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getEnhancedStrategy(id: string): Promise<any> {
|
||||
return this.handleRequest(async () => {
|
||||
const response = await apiClient.get(`${this.baseURL}/enhanced-strategies/${id}`);
|
||||
return response.data.data || response.data;
|
||||
});
|
||||
}
|
||||
|
||||
async generateEnhancedAIRecommendations(strategyId: string): Promise<any> {
|
||||
return this.handleRequest(async () => {
|
||||
const response = await apiClient.post(`${this.baseURL}/enhanced-strategies/${strategyId}/ai-recommendations`);
|
||||
return response.data.data || response.data;
|
||||
}, true);
|
||||
}
|
||||
|
||||
async regenerateAIAnalysis(strategyId: string, analysisType: string): Promise<any> {
|
||||
return this.handleRequest(async () => {
|
||||
const response = await apiClient.post(`${this.baseURL}/enhanced-strategies/${strategyId}/ai-analysis/regenerate`, {
|
||||
analysis_type: analysisType
|
||||
});
|
||||
return response.data;
|
||||
}, true);
|
||||
}
|
||||
|
||||
async getEnhancedAIAnalyses(strategyId: string): Promise<any> {
|
||||
return this.handleRequest(async () => {
|
||||
const response = await apiClient.get(`${this.baseURL}/enhanced-strategies/${strategyId}/ai-analyses`);
|
||||
return response.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getOnboardingData(userId?: number): Promise<any> {
|
||||
return this.handleRequest(async () => {
|
||||
const params = userId ? { user_id: userId } : {};
|
||||
const response = await apiClient.get(`${this.baseURL}/enhanced-strategies/onboarding-data`, { params });
|
||||
return response.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getOnboardingIntegration(strategyId: string): Promise<any> {
|
||||
return this.handleRequest(async () => {
|
||||
const response = await apiClient.get(`${this.baseURL}/enhanced-strategies/${strategyId}/onboarding-integration`);
|
||||
return response.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getEnhancedStrategyAnalytics(strategyId: string): Promise<any> {
|
||||
return this.handleRequest(async () => {
|
||||
const response = await apiClient.get(`${this.baseURL}/enhanced-strategies/${strategyId}/analytics`);
|
||||
return response.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getEnhancedStrategyCompletion(strategyId: string): Promise<any> {
|
||||
return this.handleRequest(async () => {
|
||||
const response = await apiClient.get(`${this.baseURL}/enhanced-strategies/${strategyId}/completion`);
|
||||
@@ -776,22 +583,6 @@ class ContentPlanningAPI {
|
||||
});
|
||||
}
|
||||
|
||||
// Enhanced Strategy Streaming Methods
|
||||
async streamEnhancedStrategies(userId?: number): Promise<EventSource> {
|
||||
const url = `${this.baseURL}/enhanced-strategies/stream/strategies?user_id=${userId || 1}`;
|
||||
return new EventSource(url);
|
||||
}
|
||||
|
||||
async streamStrategicIntelligence(userId?: number): Promise<EventSource> {
|
||||
const url = `${this.baseURL}/enhanced-strategies/stream/strategic-intelligence?user_id=${userId || 1}`;
|
||||
return new EventSource(url);
|
||||
}
|
||||
|
||||
async streamKeywordResearch(userId?: number): Promise<EventSource> {
|
||||
const url = `${this.baseURL}/enhanced-strategies/stream/keyword-research?user_id=${userId || 1}`;
|
||||
return new EventSource(url);
|
||||
}
|
||||
|
||||
// Clear enhanced strategy streaming/cache for a user (best-effort refresh)
|
||||
async clearEnhancedCache(userId?: number): Promise<any> {
|
||||
const params: any = {};
|
||||
@@ -800,21 +591,7 @@ class ContentPlanningAPI {
|
||||
return response.data;
|
||||
}
|
||||
|
||||
// Stream AI generation/status updates for a specific strategy (best-effort)
|
||||
async streamAIGenerationStatus(strategyId: number | string): Promise<EventSource> {
|
||||
const url = `${this.baseURL}/enhanced-strategies/stream/strategies?strategy_id=${strategyId}`;
|
||||
return new EventSource(url);
|
||||
}
|
||||
|
||||
async streamAutofillRefresh(userId?: number, useAI: boolean = true, aiOnly: boolean = false): Promise<EventSource> {
|
||||
const params = new URLSearchParams();
|
||||
if (userId) params.append('user_id', String(userId));
|
||||
params.append('use_ai', String(useAI));
|
||||
params.append('ai_only', String(aiOnly));
|
||||
const url = `${this.baseURL}/enhanced-strategies/autofill/refresh/stream?${params.toString()}`;
|
||||
return new EventSource(url);
|
||||
}
|
||||
|
||||
// Non-streaming autofill refresh method
|
||||
async refreshAutofill(userId?: number, useAI: boolean = true, aiOnly: boolean = false): Promise<any> {
|
||||
const params: any = { use_ai: useAI, ai_only: aiOnly };
|
||||
if (userId) params.user_id = userId;
|
||||
@@ -822,7 +599,68 @@ class ContentPlanningAPI {
|
||||
return response.data;
|
||||
}
|
||||
|
||||
// Helper method to handle SSE data
|
||||
// Enhanced Strategy CRUD Operations
|
||||
async updateEnhancedStrategy(id: string, updates: any): Promise<any> {
|
||||
return this.handleRequest(async () => {
|
||||
const response = await apiClient.put(`${this.baseURL}/enhanced-strategies/${id}`, updates);
|
||||
return response.data.data || response.data;
|
||||
});
|
||||
}
|
||||
|
||||
async deleteEnhancedStrategy(id: string): Promise<any> {
|
||||
return this.handleRequest(async () => {
|
||||
const response = await apiClient.delete(`${this.baseURL}/enhanced-strategies/${id}`);
|
||||
return response.data.data || response.data;
|
||||
});
|
||||
}
|
||||
|
||||
// Onboarding Data Methods
|
||||
async getOnboardingData(userId?: number): Promise<any> {
|
||||
return this.handleRequest(async () => {
|
||||
const params = userId ? { user_id: userId } : {};
|
||||
const response = await apiClient.get(`${this.baseURL}/enhanced-strategies/onboarding-data`, { params });
|
||||
return response.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getOnboardingIntegration(strategyId: string): Promise<any> {
|
||||
return this.handleRequest(async () => {
|
||||
const response = await apiClient.get(`${this.baseURL}/enhanced-strategies/${strategyId}/onboarding-integration`);
|
||||
return response.data;
|
||||
});
|
||||
}
|
||||
|
||||
// AI Analysis Methods
|
||||
async generateEnhancedAIRecommendations(strategyId: string): Promise<any> {
|
||||
return this.handleRequest(async () => {
|
||||
const response = await apiClient.post(`${this.baseURL}/enhanced-strategies/${strategyId}/ai-recommendations`);
|
||||
return response.data.data || response.data;
|
||||
}, true);
|
||||
}
|
||||
|
||||
async regenerateAIAnalysis(strategyId: string, analysisType: string): Promise<any> {
|
||||
return this.handleRequest(async () => {
|
||||
const response = await apiClient.post(`${this.baseURL}/enhanced-strategies/${strategyId}/ai-analysis/regenerate`, {
|
||||
analysis_type: analysisType
|
||||
});
|
||||
return response.data;
|
||||
}, true);
|
||||
}
|
||||
|
||||
async getEnhancedAIAnalyses(strategyId: string): Promise<any> {
|
||||
return this.handleRequest(async () => {
|
||||
const response = await apiClient.get(`${this.baseURL}/enhanced-strategies/${strategyId}/ai-analyses`);
|
||||
return response.data;
|
||||
});
|
||||
}
|
||||
|
||||
// SSE Methods (for Orchestrator - real-time updates needed)
|
||||
async streamStrategicIntelligence(userId?: number): Promise<EventSource> {
|
||||
const url = `${this.baseURL}/enhanced-strategies/stream/strategic-intelligence?user_id=${userId || 1}`;
|
||||
return new EventSource(url);
|
||||
}
|
||||
|
||||
// Helper method to handle SSE data (for Orchestrator)
|
||||
handleSSEData(eventSource: EventSource, onData: (data: any) => void, onError?: (error: any) => void, onComplete?: () => void) {
|
||||
eventSource.onmessage = (event) => {
|
||||
try {
|
||||
@@ -848,6 +686,26 @@ class ContentPlanningAPI {
|
||||
|
||||
return eventSource;
|
||||
}
|
||||
|
||||
// Polling and Status Methods
|
||||
async getLatestGeneratedStrategy(userId?: number): Promise<any> {
|
||||
return this.handleRequest(async () => {
|
||||
const params = userId ? { user_id: userId } : {};
|
||||
const response = await apiClient.get(`${this.baseURL}/enhanced-strategies/latest-generated`, { params });
|
||||
return response.data;
|
||||
});
|
||||
}
|
||||
|
||||
// Additional SSE Methods (for other features that need real-time updates)
|
||||
async streamKeywordResearch(userId?: number): Promise<EventSource> {
|
||||
const url = `${this.baseURL}/enhanced-strategies/stream/keyword-research?user_id=${userId || 1}`;
|
||||
return new EventSource(url);
|
||||
}
|
||||
|
||||
async streamAIGenerationStatus(strategyId: string | number): Promise<EventSource> {
|
||||
const url = `${this.baseURL}/enhanced-strategies/stream/ai-generation-status?strategy_id=${strategyId}`;
|
||||
return new EventSource(url);
|
||||
}
|
||||
}
|
||||
|
||||
// Export singleton instance
|
||||
|
||||
@@ -160,6 +160,7 @@ interface EnhancedStrategyStore {
|
||||
dataSources: Record<string, string>;
|
||||
inputDataPoints: Record<string, any>; // Detailed input data points from backend
|
||||
personalizationData: Record<string, any>; // Personalization data for each field
|
||||
confidenceScores: Record<string, number>; // Confidence scores for each field
|
||||
|
||||
// UI State
|
||||
loading: boolean;
|
||||
@@ -167,12 +168,29 @@ interface EnhancedStrategyStore {
|
||||
saving: boolean;
|
||||
aiGenerating: boolean;
|
||||
|
||||
// Transparency State
|
||||
transparencyModalOpen: boolean;
|
||||
generationProgress: number;
|
||||
currentPhase: string;
|
||||
educationalContent: any;
|
||||
transparencyMessages: string[];
|
||||
isGenerating: boolean;
|
||||
|
||||
// Actions
|
||||
setLoading: (loading: boolean) => void;
|
||||
setError: (error: string | null) => void;
|
||||
setSaving: (saving: boolean) => void;
|
||||
setAIGenerating: (generating: boolean) => void;
|
||||
|
||||
// Transparency actions
|
||||
setTransparencyModalOpen: (open: boolean) => void;
|
||||
setGenerationProgress: (progress: number) => void;
|
||||
setCurrentPhase: (phase: string) => void;
|
||||
setEducationalContent: (content: any) => void;
|
||||
addTransparencyMessage: (message: string) => void;
|
||||
clearTransparencyMessages: () => void;
|
||||
setIsGenerating: (generating: boolean) => void;
|
||||
|
||||
// Strategy actions
|
||||
createEnhancedStrategy: (strategy: Partial<EnhancedStrategy>) => Promise<EnhancedStrategy>;
|
||||
updateEnhancedStrategy: (id: string, updates: Partial<EnhancedStrategy>) => Promise<void>;
|
||||
@@ -604,6 +622,7 @@ export const useEnhancedStrategyStore = create<EnhancedStrategyStore>((set, get)
|
||||
dataSources: {},
|
||||
inputDataPoints: {}, // Initialize inputDataPoints
|
||||
personalizationData: {}, // Initialize personalizationData
|
||||
confidenceScores: {}, // Initialize confidenceScores
|
||||
|
||||
// UI State
|
||||
loading: false,
|
||||
@@ -611,12 +630,31 @@ export const useEnhancedStrategyStore = create<EnhancedStrategyStore>((set, get)
|
||||
saving: false,
|
||||
aiGenerating: false,
|
||||
|
||||
// Transparency State
|
||||
transparencyModalOpen: false,
|
||||
generationProgress: 0,
|
||||
currentPhase: '',
|
||||
educationalContent: null,
|
||||
transparencyMessages: [],
|
||||
isGenerating: false,
|
||||
|
||||
// Actions
|
||||
setLoading: (loading) => set({ loading }),
|
||||
setError: (error) => set({ error }),
|
||||
setSaving: (saving) => set({ saving }),
|
||||
setAIGenerating: (generating) => set({ aiGenerating: generating }),
|
||||
|
||||
// Transparency actions
|
||||
setTransparencyModalOpen: (open) => set({ transparencyModalOpen: open }),
|
||||
setGenerationProgress: (progress) => set({ generationProgress: progress }),
|
||||
setCurrentPhase: (phase) => set({ currentPhase: phase }),
|
||||
setEducationalContent: (content) => set({ educationalContent: content }),
|
||||
addTransparencyMessage: (message) => set((state) => ({
|
||||
transparencyMessages: [...state.transparencyMessages, message]
|
||||
})),
|
||||
clearTransparencyMessages: () => set({ transparencyMessages: [] }),
|
||||
setIsGenerating: (generating) => set({ isGenerating: generating }),
|
||||
|
||||
// Strategy actions
|
||||
createEnhancedStrategy: async (strategy) => {
|
||||
set({ saving: true, error: null });
|
||||
@@ -725,8 +763,16 @@ export const useEnhancedStrategyStore = create<EnhancedStrategyStore>((set, get)
|
||||
dataSources: {},
|
||||
inputDataPoints: {}, // Reset inputDataPoints
|
||||
personalizationData: {}, // Reset personalizationData
|
||||
confidenceScores: {}, // Reset confidenceScores
|
||||
currentStep: 0,
|
||||
completedSteps: []
|
||||
completedSteps: [],
|
||||
// Reset transparency state
|
||||
transparencyModalOpen: false,
|
||||
generationProgress: 0,
|
||||
currentPhase: '',
|
||||
educationalContent: null,
|
||||
transparencyMessages: [],
|
||||
isGenerating: false
|
||||
});
|
||||
},
|
||||
|
||||
@@ -793,6 +839,7 @@ export const useEnhancedStrategyStore = create<EnhancedStrategyStore>((set, get)
|
||||
const fieldValues: Record<string, any> = {};
|
||||
const autoPopulatedFields: Record<string, any> = {};
|
||||
const personalizationData: Record<string, any> = {};
|
||||
const confidenceScores: Record<string, number> = {}; // Initialize confidenceScores
|
||||
|
||||
Object.keys(fields).forEach(fieldId => {
|
||||
const fieldData = fields[fieldId];
|
||||
@@ -808,6 +855,12 @@ export const useEnhancedStrategyStore = create<EnhancedStrategyStore>((set, get)
|
||||
console.log(`🎯 Personalization data for ${fieldId}:`, fieldData.personalization_data);
|
||||
}
|
||||
|
||||
// Extract confidence score if available
|
||||
if (fieldData.confidence_score) {
|
||||
confidenceScores[fieldId] = fieldData.confidence_score;
|
||||
console.log(`💯 Confidence score for ${fieldId}:`, fieldData.confidence_score);
|
||||
}
|
||||
|
||||
console.log(`✅ Auto-populated ${fieldId}:`, fieldData.value);
|
||||
} else {
|
||||
console.log(`❌ Skipping ${fieldId} - invalid data structure`);
|
||||
@@ -817,12 +870,14 @@ export const useEnhancedStrategyStore = create<EnhancedStrategyStore>((set, get)
|
||||
console.log('📝 Final field values:', fieldValues);
|
||||
console.log('🔄 Final auto-populated fields:', autoPopulatedFields);
|
||||
console.log('🎯 Personalization data:', personalizationData);
|
||||
console.log('💯 Confidence scores:', confidenceScores);
|
||||
|
||||
set((state) => ({
|
||||
autoPopulatedFields,
|
||||
dataSources: sources,
|
||||
inputDataPoints, // Store the detailed input data points
|
||||
personalizationData, // Store personalization data
|
||||
confidenceScores, // Store confidence scores
|
||||
formData: { ...state.formData, ...fieldValues }
|
||||
}));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user