ALwrity version 0.5.5

This commit is contained in:
ajaysi
2025-08-15 16:13:01 +05:30
parent 55a97b2fd4
commit 6bfa9f0fce
23 changed files with 3436 additions and 115 deletions

View File

@@ -1,4 +1,5 @@
import React, { useState, useEffect } from 'react';
import { useLocation } from 'react-router-dom';
import {
Box,
Tabs,
@@ -72,6 +73,7 @@ function a11yProps(index: number) {
}
const ContentPlanningDashboard: React.FC = () => {
const location = useLocation();
const [activeTab, setActiveTab] = useState(0);
const [serviceStatuses, setServiceStatuses] = useState<ServiceStatus[]>([]);
const [dashboardData, setDashboardData] = useState<DashboardData>({
@@ -121,6 +123,13 @@ const ContentPlanningDashboard: React.FC = () => {
});
}, [updateStrategies, updateCalendarEvents, updateGapAnalyses, updateAIInsights]);
// Handle navigation state for active tab
useEffect(() => {
if (location.state?.activeTab !== undefined) {
setActiveTab(location.state.activeTab);
}
}, [location.state]);
// Load dashboard data using orchestrator
useEffect(() => {
const loadDashboardData = async () => {

View File

@@ -1,4 +1,5 @@
import React, { useState, useEffect, useRef } from 'react';
import { useNavigate } from 'react-router-dom';
import {
Box,
Paper,
@@ -60,6 +61,7 @@ import EnhancedTooltip from './ContentStrategyBuilder/EnhancedTooltip';
import AIRecommendationsPanel from './AIRecommendationsPanel';
import DataSourceTransparency from './DataSourceTransparency';
import StrategyAutofillTransparencyModal from './StrategyAutofillTransparencyModal';
import EnterpriseDatapointsModal from './EnterpriseDatapointsModal';
// Import extracted hooks
import { useCategoryReview } from './ContentStrategyBuilder/hooks/useCategoryReview';
@@ -83,6 +85,7 @@ import { contentPlanningApi } from '../../../services/contentPlanningApi';
import CategoryDetailView from './ContentStrategyBuilder/components/CategoryDetailView';
const ContentStrategyBuilder: React.FC = () => {
const navigate = useNavigate();
const {
formData,
formErrors,
@@ -143,6 +146,31 @@ const ContentStrategyBuilder: React.FC = () => {
const [refreshError, setRefreshError] = useState<string | null>(null);
const [showEducationalModal, setShowEducationalModal] = useState(false);
const [localEducationalContent, setLocalEducationalContent] = useState<any>(null);
const [showEnterpriseModal, setShowEnterpriseModal] = useState(false);
// Persist enterprise modal state across hot reloads
useEffect(() => {
const savedModalState = sessionStorage.getItem('showEnterpriseModal');
if (savedModalState === 'true') {
console.log('🎯 Restoring enterprise modal state from sessionStorage');
setShowEnterpriseModal(true);
}
}, []);
// Save modal state to sessionStorage when it changes
useEffect(() => {
sessionStorage.setItem('showEnterpriseModal', showEnterpriseModal.toString());
}, [showEnterpriseModal]);
// Cleanup sessionStorage on component unmount
useEffect(() => {
return () => {
// Only clear if we're not in the middle of showing the modal
if (!showEnterpriseModal) {
sessionStorage.removeItem('showEnterpriseModal');
}
};
}, [showEnterpriseModal]);
const [localGenerationProgress, setLocalGenerationProgress] = useState<number>(0);
const [showAIRecModal, setShowAIRecModal] = useState(false);
@@ -178,7 +206,7 @@ const ContentStrategyBuilder: React.FC = () => {
});
// Use ActionButtons business logic hook
const { handleCreateStrategy, handleSaveStrategy } = useActionButtonsBusinessLogic({
const { handleCreateStrategy: originalHandleCreateStrategy, handleSaveStrategy } = useActionButtonsBusinessLogic({
formData,
error,
currentStrategy,
@@ -196,6 +224,92 @@ const ContentStrategyBuilder: React.FC = () => {
contentPlanningApi
});
// Enhanced handleCreateStrategy to show enterprise modal
const handleCreateStrategy = () => {
console.log('🎯 handleCreateStrategy called');
console.log('🎯 completionStats.category_completion:', completionStats.category_completion);
console.log('🎯 reviewedCategories:', reviewedCategories);
console.log('🎯 Current showEnterpriseModal state:', showEnterpriseModal);
console.log('🎯 Current aiGenerating state:', aiGenerating);
// Prevent multiple calls
if (aiGenerating) {
console.log('🎯 Already generating, skipping duplicate call');
return;
}
// Check if all categories are reviewed
const allCategoriesReviewed = Object.keys(completionStats.category_completion).every(
category => Array.from(reviewedCategories).includes(category)
);
console.log('🎯 allCategoriesReviewed:', allCategoriesReviewed);
if (allCategoriesReviewed) {
// Show enterprise modal instead of creating strategy immediately
console.log('🎯 Showing enterprise modal - setting to true');
setShowEnterpriseModal(true);
// Add debugging to confirm modal state change
setTimeout(() => {
console.log('🎯 Enterprise modal state after setShowEnterpriseModal(true):', showEnterpriseModal);
}, 0);
// Return early to prevent calling originalHandleCreateStrategy
return;
} else {
// If not all categories reviewed, proceed with original logic
console.log('🎯 Not all categories reviewed, proceeding with original logic');
originalHandleCreateStrategy();
}
};
// Handle proceed with current strategy (30 fields)
const handleProceedWithCurrentStrategy = async () => {
console.log('🎯 User clicked "Proceed with Current Strategy"');
setShowEnterpriseModal(false);
sessionStorage.removeItem('showEnterpriseModal'); // Clear sessionStorage
// Add a small delay to ensure modal closes properly before showing educational modal
setTimeout(async () => {
console.log('🎯 Calling original handleCreateStrategy after enterprise modal closes');
try {
// Ensure we're not already generating
if (!aiGenerating) {
console.log('🎯 Starting strategy generation...');
await originalHandleCreateStrategy();
} else {
console.log('🎯 Already generating, skipping duplicate call');
}
} catch (error) {
console.error('🎯 Error in handleProceedWithCurrentStrategy:', error);
}
}, 300); // Increased delay to ensure modal closes completely
};
// Handle add enterprise datapoints (coming soon)
const handleAddEnterpriseDatapoints = async () => {
console.log('🎯 User clicked "Add Enterprise Datapoints"');
setShowEnterpriseModal(false);
sessionStorage.removeItem('showEnterpriseModal'); // Clear sessionStorage
// For now, just proceed with current strategy
// In Phase 2, this will enable enterprise datapoints
setTimeout(async () => {
console.log('🎯 Calling original handleCreateStrategy for enterprise datapoints');
try {
// Ensure we're not already generating
if (!aiGenerating) {
await originalHandleCreateStrategy();
} else {
console.log('🎯 Already generating, skipping duplicate call');
}
} catch (error) {
console.error('🎯 Error in handleAddEnterpriseDatapoints:', error);
}
}, 200); // Increased delay to ensure modal closes completely
};
// Auto-populate from onboarding on first load
useEffect(() => {
if (!autoPopulateAttempted) {
@@ -231,6 +345,24 @@ const ContentStrategyBuilder: React.FC = () => {
console.log('🎯 Modal state changed - transparencyModalOpen:', transparencyModalOpen);
}, [transparencyModalOpen]);
// Monitor enterprise modal state for debugging
useEffect(() => {
console.log('🎯 Enterprise modal state changed - showEnterpriseModal:', showEnterpriseModal);
// If modal was unexpectedly closed, log it
if (!showEnterpriseModal && aiGenerating) {
console.warn('🎯 WARNING: Enterprise modal closed while AI is generating');
}
// Only warn about unexpected closure if it's not due to hot reload
if (!showEnterpriseModal && !aiGenerating) {
const savedModalState = sessionStorage.getItem('showEnterpriseModal');
if (savedModalState !== 'true') {
console.warn('🎯 WARNING: Enterprise modal closed unexpectedly (not due to hot reload)');
}
}
}, [showEnterpriseModal, aiGenerating]);
// Monitor store data changes for debugging
useEffect(() => {
console.log('🎯 Store data changed:', {
@@ -493,20 +625,17 @@ const ContentStrategyBuilder: React.FC = () => {
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);
// Don't close modal automatically - let user close it manually
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()
});
} else {
throw new Error('Invalid response from AI refresh endpoint');
}
@@ -656,8 +785,16 @@ const ContentStrategyBuilder: React.FC = () => {
<EducationalModal
open={showEducationalModal}
onClose={() => setShowEducationalModal(false)}
educationalContent={storeEducationalContent}
educationalContent={storeEducationalContent}
generationProgress={storeGenerationProgress}
onReviewStrategy={() => {
console.log('🎯 User clicked "Next: Review Strategy and Create Calendar"');
setShowEducationalModal(false);
// Navigate to content planning dashboard with Content Strategy tab active
navigate('/content-planning', {
state: { activeTab: 0 } // 0 = Content Strategy tab
});
}}
/>
{/* Data Source Transparency Modal */}
@@ -690,7 +827,13 @@ const ContentStrategyBuilder: React.FC = () => {
{/* Strategy Autofill Transparency Modal */}
<StrategyAutofillTransparencyModal
open={transparencyModalOpen}
onClose={() => setTransparencyModalOpen(false)}
onClose={() => {
setTransparencyModalOpen(false);
// Ensure form data is refreshed after modal closes
console.log('🎯 Modal closed - ensuring form data is updated');
console.log('🎯 Current autoPopulatedFields:', Object.keys(autoPopulatedFields || {}));
console.log('🎯 Current formData keys:', Object.keys(formData || {}));
}}
autoPopulatedFields={autoPopulatedFields}
dataSources={dataSources}
inputDataPoints={inputDataPoints}
@@ -702,6 +845,19 @@ const ContentStrategyBuilder: React.FC = () => {
error={error}
/>
{/* Enterprise Datapoints Modal */}
<EnterpriseDatapointsModal
open={showEnterpriseModal}
onClose={() => {
console.log('🎯 Enterprise modal onClose called');
console.log('🎯 Current aiGenerating state:', aiGenerating);
setShowEnterpriseModal(false);
sessionStorage.removeItem('showEnterpriseModal'); // Clear sessionStorage
}}
onProceedWithCurrent={handleProceedWithCurrentStrategy}
onAddEnterpriseDatapoints={handleAddEnterpriseDatapoints}
/>
{/* Tooltip */}
{showTooltip && (
<EnhancedTooltip

View File

@@ -410,7 +410,113 @@ const StrategicInputField: React.FC<StrategicInputFieldProps> = ({
<Autocomplete
multiple
options={multiSelectConfig.options || []}
value={Array.isArray(value) ? value : []}
isOptionEqualToValue={(option, value) => {
// Custom equality test that handles various formats
if (typeof option === 'string' && typeof value === 'string') {
return option.toLowerCase() === value.toLowerCase();
}
return option === value;
}}
value={(() => {
// Debug logging for Autocomplete value parsing
console.log('🎯 Autocomplete value parsing:', {
fieldId,
originalValue: value,
valueType: typeof value,
isArray: Array.isArray(value),
availableOptions: multiSelectConfig.options
});
let parsedValues: string[] = [];
if (Array.isArray(value)) {
parsedValues = value;
console.log('🎯 Using array value:', parsedValues);
} else if (typeof value === 'object' && value !== null) {
// Handle object values (convert to array of keys or values)
if (typeof value === 'object' && !Array.isArray(value)) {
// Convert object to array of keys or values based on context
const objectKeys = Object.keys(value);
const objectValues = Object.values(value);
// For traffic_sources, we might want to use the keys or convert percentages to options
if (fieldId === 'traffic_sources') {
// Convert percentage object to traffic source options
const trafficMapping: { [key: string]: string } = {
'organic': 'Organic Search',
'social': 'Social Media',
'direct': 'Direct Traffic',
'referral': 'Referral Traffic',
'paid': 'Paid Search',
'display': 'Display Advertising',
'content': 'Content Marketing',
'influencer': 'Influencer Marketing',
'video': 'Video Platforms',
'email': 'Email Marketing'
};
parsedValues = objectKeys
.map(key => trafficMapping[key.toLowerCase()])
.filter(Boolean);
console.log('🎯 Converted object to traffic sources:', parsedValues);
} else {
// For other fields, use object keys
parsedValues = objectKeys;
console.log('🎯 Using object keys:', parsedValues);
}
}
} else if (typeof value === 'string') {
try {
// Try to parse as JSON array
const parsed = JSON.parse(value);
if (Array.isArray(parsed)) {
parsedValues = parsed;
console.log('🎯 Parsed as JSON array:', parsedValues);
}
} catch (error) {
console.log('🎯 JSON parse failed, trying alternative parsing');
// If not valid JSON, try to extract array-like content
if (value.startsWith('[') && value.endsWith(']')) {
// Remove outer brackets and try to parse as comma-separated
const content = value.slice(1, -1);
// Split by comma but be careful with nested quotes
parsedValues = content.split(',').map(item => {
// Remove quotes and trim
return item.trim().replace(/^["']|["']$/g, '');
}).filter(item => item);
console.log('🎯 Parsed as array-like string:', parsedValues);
} else if (value.includes(',')) {
// If not array-like, try simple comma splitting
parsedValues = value.split(',').map(item => item.trim()).filter(item => item);
console.log('🎯 Parsed as comma-separated string:', parsedValues);
}
}
}
// Filter values to only include valid options
const validOptions = multiSelectConfig.options || [];
const filteredValues = parsedValues.filter(val => {
// Check for exact match
if (validOptions.includes(val)) {
return true;
}
// Check for partial match (case-insensitive)
const partialMatch = validOptions.find(option =>
option.toLowerCase().includes(val.toLowerCase()) ||
val.toLowerCase().includes(option.toLowerCase())
);
if (partialMatch) {
console.log('🎯 Found partial match:', val, '->', partialMatch);
return true;
}
console.log('🎯 No match found for:', val);
return false;
});
console.log('🎯 Final filtered values:', filteredValues);
return filteredValues;
})()}
onChange={(_, newValue) => handleChange(newValue)}
renderInput={(params) => (
<TextField

View File

@@ -38,34 +38,28 @@ export const useActionButtonsBusinessLogic = ({
console.log('Current formData:', formData);
console.log('FormData ID:', formData.id);
// If we have a saved strategy, use its ID
if (formData.id) {
console.log('Using existing strategy ID:', formData.id);
await generateAIRecommendations(formData.id);
} else {
console.log('No strategy ID found, creating new strategy...');
// If no strategy is saved yet, save it first, then generate AI insights
const isValid = validateAllFields();
console.log('Form validation result:', isValid);
if (isValid) {
const completionStats = getCompletionStats();
const strategyData = {
...formData,
completion_percentage: completionStats.completion_percentage,
user_id: 1, // This would come from auth context
name: formData.name || 'Enhanced Content Strategy',
industry: formData.industry || 'General'
};
// Always use the polling-based strategy generation for consistency
console.log('Using polling-based strategy generation...');
const isValid = validateAllFields();
console.log('Form validation result:', isValid);
if (isValid) {
const completionStats = getCompletionStats();
const strategyData = {
...formData,
completion_percentage: completionStats.completion_percentage,
user_id: 1, // This would come from auth context
name: formData.name || 'Enhanced Content Strategy',
industry: formData.industry || 'General'
};
console.log('Attempting to create strategy with data:', strategyData);
// Use SSE streaming endpoint for strategy generation with educational content
await generateStrategyWithPolling(strategyData);
} else {
setError('Please fill in all required fields before generating AI insights.');
console.error('Form validation failed. Cannot generate AI insights.');
}
console.log('Attempting to create strategy with data:', strategyData);
// Use polling-based strategy generation with educational content
await generateStrategyWithPolling(strategyData);
} else {
setError('Please fill in all required fields before generating AI insights.');
console.error('Form validation failed. Cannot generate AI insights.');
}
} catch (err: any) {
setError(`Error generating AI recommendations: ${err.message || 'Unknown error'}`);
@@ -97,49 +91,79 @@ export const useActionButtonsBusinessLogic = ({
// Show educational modal
setShowEducationalModal(true);
// Start polling-based strategy generation directly (no basic strategy creation)
const generationResult = await contentPlanningApi.startStrategyGenerationPolling(1, 'Enhanced Content Strategy');
// Start polling-based strategy generation with actual strategy data
const generationResult = await contentPlanningApi.startStrategyGenerationPolling(
strategyData.user_id || 1,
strategyData.name || 'Enhanced Content Strategy'
);
console.log('Strategy generation started:', generationResult);
console.log('Generation result structure:', generationResult);
console.log('Generation result.data:', generationResult?.data);
console.log('Generation result.data.task_id:', generationResult?.data?.task_id);
if (generationResult && generationResult.task_id) {
const taskId = generationResult.task_id;
// Check for task_id in the correct location based on backend response structure
const taskId = generationResult?.data?.task_id || generationResult?.task_id;
console.log('Task ID extracted:', taskId);
if (taskId) {
console.log('Task ID received:', taskId);
// Start polling for status updates
console.log('🎯 Starting polling for task ID:', taskId);
contentPlanningApi.pollStrategyGeneration(
taskId,
// onProgress callback
(status: any) => {
console.log('📊 Progress update:', status);
console.log('📊 Status structure:', status);
// Extract the actual task status from the response data
const taskStatus = status?.data || status;
console.log('📊 Task status:', taskStatus);
// Update progress
if (status.progress !== undefined) {
setGenerationProgress(status.progress);
if (taskStatus.progress !== undefined) {
console.log('📊 Setting progress:', taskStatus.progress);
setGenerationProgress(taskStatus.progress);
// Debug: Check if progress reached 100%
if (taskStatus.progress >= 100) {
console.log('🎯 Progress reached 100% - modal should show "Next" button');
}
}
// Update educational content
if (status.educational_content) {
console.log('📚 Updating educational content:', status.educational_content);
setEducationalContent(status.educational_content);
if (taskStatus.educational_content) {
console.log('📚 Updating educational content:', taskStatus.educational_content);
setEducationalContent(taskStatus.educational_content);
}
// Update message
if (status.message) {
console.log('📝 Status message:', status.message);
if (taskStatus.message) {
console.log('📝 Status message:', taskStatus.message);
}
// Update phase if available
if (taskStatus.step) {
console.log('📊 Current step:', taskStatus.step);
}
},
// onComplete callback
(strategy: any) => {
console.log('✅ Strategy generation completed successfully!');
setCurrentStrategy(strategy);
setShowEducationalModal(false);
setError('Strategy created successfully! Check the Strategic Intelligence tab for detailed insights.');
// Set progress to 100% when completion is detected
setGenerationProgress(100);
console.log('🎯 Setting progress to 100% in onComplete callback');
// Don't close the modal automatically - let user click the button
// setShowEducationalModal(false); // REMOVED - let user control modal closure
console.log('🎯 Strategy generation complete - modal should stay open for user to click "Next" button');
},
// onError callback
(error: string) => {
console.error('❌ Strategy generation failed:', error);
setError(`Strategy generation failed: ${error}`);
setShowEducationalModal(false);
setShowEducationalModal(false); // Only close on error
},
5000, // 5 second polling interval for faster updates
72 // 6 minutes max (72 * 5 seconds)

View File

@@ -31,8 +31,11 @@ const EducationalModal: React.FC<EducationalModalProps> = ({
open,
onClose,
educationalContent,
generationProgress
generationProgress,
onReviewStrategy
}) => {
// Debug: Log progress and button state
console.log('🎯 EducationalModal - Progress:', generationProgress, 'Show Next Button:', generationProgress >= 100);
return (
<Dialog
open={open}
@@ -528,24 +531,50 @@ const EducationalModal: React.FC<EducationalModalProps> = ({
pt: 0,
justifyContent: 'center'
}}>
<Button
variant="outlined"
onClick={onClose}
sx={{
borderRadius: 2,
px: 4,
py: 1.5,
fontWeight: 600,
borderColor: 'rgba(102, 126, 234, 0.3)',
color: '#667eea',
'&:hover': {
borderColor: '#667eea',
backgroundColor: 'rgba(102, 126, 234, 0.05)'
}
}}
>
Close
</Button>
{generationProgress >= 100 ? (
// Show "Next: Review Strategy and Create Calendar" button when generation is complete
<Button
variant="contained"
onClick={onReviewStrategy}
sx={{
borderRadius: 2,
px: 4,
py: 1.5,
fontWeight: 600,
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
color: 'white',
'&:hover': {
background: 'linear-gradient(135deg, #5a6fd8 0%, #6a4190 100%)',
transform: 'translateY(-1px)',
boxShadow: '0 8px 25px rgba(102, 126, 234, 0.3)'
},
transition: 'all 0.3s ease'
}}
startIcon={<AutoAwesomeIcon />}
>
Next: Review Strategy and Create Calendar
</Button>
) : (
// Show "Close" button during generation
<Button
variant="outlined"
onClick={onClose}
sx={{
borderRadius: 2,
px: 4,
py: 1.5,
fontWeight: 600,
borderColor: 'rgba(102, 126, 234, 0.3)',
color: '#667eea',
'&:hover': {
borderColor: '#667eea',
backgroundColor: 'rgba(102, 126, 234, 0.05)'
}
}}
>
Close
</Button>
)}
</DialogActions>
</Dialog>
);

View File

@@ -17,6 +17,7 @@ export interface EducationalModalProps {
onClose: () => void;
educationalContent: EducationalContent | null;
generationProgress: number;
onReviewStrategy?: () => void;
}
// Category Detail View Types

View File

@@ -0,0 +1,511 @@
import React from 'react';
import {
Dialog,
DialogTitle,
DialogContent,
DialogActions,
Button,
Typography,
Box,
Grid,
Card,
CardContent,
Chip,
List,
ListItem,
ListItemIcon,
ListItemText,
Divider,
Alert,
IconButton,
Paper
} from '@mui/material';
import {
AutoAwesome as AutoAwesomeIcon,
TrendingUp as TrendingUpIcon,
Business as BusinessIcon,
Analytics as AnalyticsIcon,
Schedule as ScheduleIcon,
Group as GroupIcon,
Assessment as AssessmentIcon,
Build as BuildIcon,
Palette as BrandingIcon,
Storage as StorageIcon,
CheckCircle as CheckCircleIcon,
ArrowForward as ArrowForwardIcon,
Close as CloseIcon,
Star as StarIcon,
Speed as SpeedIcon,
Security as SecurityIcon
} from '@mui/icons-material';
import { motion } from 'framer-motion';
interface EnterpriseDatapointsModalProps {
open: boolean;
onClose: () => void;
onProceedWithCurrent: () => void;
onAddEnterpriseDatapoints: () => void;
}
const EnterpriseDatapointsModal: React.FC<EnterpriseDatapointsModalProps> = ({
open,
onClose,
onProceedWithCurrent,
onAddEnterpriseDatapoints
}) => {
const enterpriseCategories = [
{
title: 'Content Distribution & Channel Strategy',
icon: <TrendingUpIcon />,
fields: 6,
description: 'Multi-channel distribution and promotion strategy',
color: 'primary'
},
{
title: 'Content Calendar & Planning',
icon: <ScheduleIcon />,
fields: 5,
description: 'Structured content planning and scheduling',
color: 'secondary'
},
{
title: 'Audience Segmentation & Personas',
icon: <GroupIcon />,
fields: 6,
description: 'Detailed audience analysis and personas',
color: 'success'
},
{
title: 'Content Performance & Optimization',
icon: <AnalyticsIcon />,
fields: 5,
description: 'Performance tracking and optimization',
color: 'info'
},
{
title: 'Content Creation & Production',
icon: <BuildIcon />,
fields: 5,
description: 'Content creation workflow and processes',
color: 'warning'
},
{
title: 'Brand & Messaging Strategy',
icon: <BrandingIcon />,
fields: 5,
description: 'Brand positioning and messaging',
color: 'error'
},
{
title: 'Technology & Platform Strategy',
icon: <StorageIcon />,
fields: 5,
description: 'Technology stack and integrations',
color: 'primary'
}
];
const benefits = [
{
icon: <StarIcon />,
title: '3x Better Performance',
description: 'Strategies with 60+ datapoints show significantly better results'
},
{
icon: <SpeedIcon />,
title: 'Months → Minutes',
description: 'Get enterprise-grade analysis in minutes, not months'
},
{
icon: <SecurityIcon />,
title: 'Risk Mitigation',
description: 'Comprehensive analysis reduces strategy risks'
},
{
icon: <BusinessIcon />,
title: '$50K+ Value',
description: 'Enterprise consulting value democratized with AI'
}
];
return (
<Dialog
open={open}
onClose={(event, reason) => {
console.log('🎯 Enterprise modal onClose called with reason:', reason);
// Only allow closing via the close button, not by clicking outside or pressing escape
if (reason === 'backdropClick' || reason === 'escapeKeyDown') {
console.log('🎯 Preventing modal close via backdrop/escape');
return;
}
onClose();
}}
maxWidth="xl"
fullWidth
disableEscapeKeyDown
PaperProps={{
sx: {
borderRadius: 4,
background: 'linear-gradient(135deg, #ffffff 0%, #f8f9ff 100%)',
boxShadow: '0 20px 60px rgba(0, 0, 0, 0.15)',
border: '1px solid rgba(102, 126, 234, 0.1)',
overflow: 'hidden',
maxHeight: '95vh'
}
}}
>
<DialogTitle sx={{
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
color: 'white',
position: 'relative',
overflow: 'hidden',
'&::before': {
content: '""',
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
background: 'linear-gradient(45deg, rgba(255,255,255,0.1) 0%, rgba(255,255,255,0) 100%)',
pointerEvents: 'none'
}
}}>
<Box display="flex" alignItems="center" justifyContent="space-between" sx={{ position: 'relative', zIndex: 1 }}>
<Box display="flex" alignItems="center" gap={2}>
<Box sx={{
p: 1,
borderRadius: 2,
background: 'rgba(255, 255, 255, 0.2)',
backdropFilter: 'blur(10px)',
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.1)'
}}>
<AutoAwesomeIcon sx={{ color: 'white', fontSize: 24 }} />
</Box>
<Box>
<Typography variant="h4" sx={{ fontWeight: 700, mb: 0.5 }}>
Unlock Enterprise-Grade Content Strategy
</Typography>
<Typography variant="body1" sx={{ opacity: 0.9, fontWeight: 500 }}>
Transform your basic strategy into an enterprise-grade content strategy that drives real results
</Typography>
</Box>
</Box>
<IconButton
onClick={onClose}
sx={{
color: 'white',
'&:hover': {
backgroundColor: 'rgba(255, 255, 255, 0.1)'
}
}}
>
<CloseIcon />
</IconButton>
</Box>
</DialogTitle>
<DialogContent sx={{ p: 0 }}>
<Box sx={{ p: 4 }}>
{/* Value Proposition Section */}
<Grid container spacing={3} sx={{ mb: 4 }}>
<Grid item xs={12} md={8}>
<Typography variant="h5" gutterBottom sx={{ color: '#667eea', fontWeight: 600 }}>
Why Enterprise Datapoints Matter
</Typography>
<Typography variant="body1" color="text.secondary" sx={{ mb: 3 }}>
Access 30+ additional datapoints that enterprise teams spend months analyzing.
Get enterprise-quality insights without the enterprise price tag.
</Typography>
<Grid container spacing={2}>
{benefits.map((benefit, index) => (
<Grid item xs={12} sm={6} key={index}>
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: index * 0.1 }}
>
<Card variant="outlined" sx={{
height: '100%',
border: '1px solid rgba(102, 126, 234, 0.1)',
'&:hover': {
borderColor: '#667eea',
boxShadow: '0 4px 12px rgba(102, 126, 234, 0.15)'
}
}}>
<CardContent sx={{ textAlign: 'center', py: 2 }}>
<Box sx={{
display: 'inline-flex',
p: 1,
borderRadius: 2,
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
color: 'white',
mb: 1
}}>
{benefit.icon}
</Box>
<Typography variant="h6" sx={{ fontWeight: 600, mb: 1 }}>
{benefit.title}
</Typography>
<Typography variant="body2" color="text.secondary">
{benefit.description}
</Typography>
</CardContent>
</Card>
</motion.div>
</Grid>
))}
</Grid>
</Grid>
<Grid item xs={12} md={4}>
<Paper sx={{
p: 3,
background: 'linear-gradient(135deg, #f8f9ff 0%, #eef3fb 100%)',
border: '2px solid rgba(102, 126, 234, 0.2)',
borderRadius: 3
}}>
<Typography variant="h6" gutterBottom sx={{ color: '#667eea', fontWeight: 600 }}>
Strategy Comparison
</Typography>
<Box sx={{ mb: 3 }}>
<Typography variant="subtitle2" color="text.secondary" gutterBottom>
Current Strategy (30 fields)
</Typography>
<List dense>
<ListItem sx={{ px: 0 }}>
<ListItemIcon sx={{ minWidth: 32 }}>
<CheckCircleIcon color="success" fontSize="small" />
</ListItemIcon>
<ListItemText
primary="Basic strategy elements"
primaryTypographyProps={{ variant: 'body2' }}
/>
</ListItem>
<ListItem sx={{ px: 0 }}>
<ListItemIcon sx={{ minWidth: 32 }}>
<CheckCircleIcon color="success" fontSize="small" />
</ListItemIcon>
<ListItemText
primary="Functional content strategy"
primaryTypographyProps={{ variant: 'body2' }}
/>
</ListItem>
<ListItem sx={{ px: 0 }}>
<ListItemIcon sx={{ minWidth: 32 }}>
<CheckCircleIcon color="success" fontSize="small" />
</ListItemIcon>
<ListItemText
primary="Quick implementation"
primaryTypographyProps={{ variant: 'body2' }}
/>
</ListItem>
</List>
</Box>
<Divider sx={{ my: 2 }} />
<Box>
<Typography variant="subtitle2" color="text.secondary" gutterBottom>
Enterprise Strategy (60+ fields)
</Typography>
<List dense>
<ListItem sx={{ px: 0 }}>
<ListItemIcon sx={{ minWidth: 32 }}>
<StarIcon color="primary" fontSize="small" />
</ListItemIcon>
<ListItemText
primary="Comprehensive coverage"
primaryTypographyProps={{ variant: 'body2' }}
/>
</ListItem>
<ListItem sx={{ px: 0 }}>
<ListItemIcon sx={{ minWidth: 32 }}>
<StarIcon color="primary" fontSize="small" />
</ListItemIcon>
<ListItemText
primary="Operational excellence"
primaryTypographyProps={{ variant: 'body2' }}
/>
</ListItem>
<ListItem sx={{ px: 0 }}>
<ListItemIcon sx={{ minWidth: 32 }}>
<StarIcon color="primary" fontSize="small" />
</ListItemIcon>
<ListItemText
primary="3x better performance"
primaryTypographyProps={{ variant: 'body2' }}
/>
</ListItem>
</List>
</Box>
</Paper>
</Grid>
</Grid>
{/* Enterprise Categories Section */}
<Box sx={{ mb: 4 }}>
<Typography variant="h5" gutterBottom sx={{ color: '#667eea', fontWeight: 600 }}>
Enterprise Datapoints Categories
</Typography>
<Typography variant="body1" color="text.secondary" sx={{ mb: 3 }}>
Unlock 30+ additional fields across 7 enterprise categories for comprehensive strategy coverage.
</Typography>
<Grid container spacing={2}>
{enterpriseCategories.map((category, index) => (
<Grid item xs={12} sm={6} md={4} key={index}>
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: index * 0.1 }}
>
<Card variant="outlined" sx={{
height: '100%',
border: '1px solid rgba(102, 126, 234, 0.1)',
'&:hover': {
borderColor: '#667eea',
transform: 'translateY(-2px)',
boxShadow: '0 8px 25px rgba(102, 126, 234, 0.15)'
},
transition: 'all 0.3s ease'
}}>
<CardContent>
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1, mb: 1 }}>
<Box sx={{
p: 0.5,
borderRadius: 1,
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
color: 'white',
display: 'flex',
alignItems: 'center'
}}>
{category.icon}
</Box>
<Chip
label={`${category.fields} fields`}
size="small"
color={category.color as any}
sx={{ fontWeight: 600 }}
/>
</Box>
<Typography variant="h6" sx={{ fontWeight: 600, mb: 1 }}>
{category.title}
</Typography>
<Typography variant="body2" color="text.secondary">
{category.description}
</Typography>
</CardContent>
</Card>
</motion.div>
</Grid>
))}
</Grid>
</Box>
{/* Process Information */}
<Alert severity="info" sx={{ mb: 3 }}>
<Typography variant="subtitle2" gutterBottom>
How It Works
</Typography>
<Typography variant="body2">
AI will autofill 80% of enterprise fields using your existing data and industry insights.
You'll only need to review and customize 20% of the fields.
Additional time: 10-15 minutes for enterprise-grade strategy.
</Typography>
</Alert>
{/* Social Proof */}
<Paper sx={{
p: 3,
background: 'linear-gradient(135deg, #f0f8ff 0%, #e6f3ff 100%)',
border: '1px solid rgba(102, 126, 234, 0.2)',
borderRadius: 2
}}>
<Typography variant="h6" gutterBottom sx={{ color: '#667eea', fontWeight: 600 }}>
What Users Say
</Typography>
<Typography variant="body1" sx={{ fontStyle: 'italic', color: 'text.secondary' }}>
"The enterprise datapoints transformed our basic strategy into a comprehensive,
actionable plan that our entire team could follow. The AI autofill saved us hours
of manual work while maintaining quality."
</Typography>
<Typography variant="body2" sx={{ mt: 1, fontWeight: 600, color: '#667eea' }}>
— Marketing Director, Tech Startup
</Typography>
</Paper>
</Box>
</DialogContent>
<DialogActions sx={{
p: 4,
pt: 0,
justifyContent: 'space-between',
flexWrap: 'wrap',
gap: 2
}}>
<Box>
<Typography variant="body2" color="text.secondary">
Limited time access to enterprise features
</Typography>
<Typography variant="body2" color="text.secondary">
Get $50K+ consulting value for free
</Typography>
</Box>
<Box sx={{ display: 'flex', gap: 2, flexWrap: 'wrap' }}>
<Button
variant="outlined"
onClick={onProceedWithCurrent}
sx={{
borderRadius: 2,
px: 3,
py: 1.5,
fontWeight: 600,
borderColor: 'rgba(102, 126, 234, 0.3)',
color: '#667eea',
'&:hover': {
borderColor: '#667eea',
backgroundColor: 'rgba(102, 126, 234, 0.05)'
}
}}
>
Proceed with Current Strategy
</Button>
<Button
variant="contained"
onClick={onAddEnterpriseDatapoints}
sx={{
borderRadius: 2,
px: 4,
py: 1.5,
fontWeight: 600,
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
'&:hover': {
background: 'linear-gradient(135deg, #5a6fd8 0%, #6a4190 100%)'
}
}}
endIcon={<ArrowForwardIcon />}
>
Add Enterprise Datapoints
<Chip
label="Coming Soon"
size="small"
sx={{
ml: 1,
backgroundColor: 'rgba(255, 255, 255, 0.2)',
color: 'white',
fontSize: '0.7rem',
height: 20
}}
/>
</Button>
</Box>
</DialogActions>
</Dialog>
);
};
export default EnterpriseDatapointsModal;