ALwrity onboarding fixes

This commit is contained in:
ajaysi
2025-10-04 13:24:41 +05:30
parent 510b79bbf8
commit 14dfb2e5c0
14 changed files with 1182 additions and 446 deletions

View File

@@ -82,13 +82,64 @@ const CompetitorAnalysisStep: React.FC<CompetitorAnalysisStepProps> = ({
const [showHighlightsModal, setShowHighlightsModal] = useState(false);
const [selectedCompetitorHighlights, setSelectedCompetitorHighlights] = useState<string[]>([]);
const [selectedCompetitorTitle, setSelectedCompetitorTitle] = useState<string>('');
const [usingCachedData, setUsingCachedData] = useState(false);
// Check for cached competitor analysis data
const loadCachedAnalysis = useCallback(() => {
try {
const cachedData = localStorage.getItem('competitor_analysis_data');
const cachedUrl = localStorage.getItem('competitor_analysis_url');
const cacheTimestamp = localStorage.getItem('competitor_analysis_timestamp');
// Get current URL for comparison
const finalUserUrl = userUrl || localStorage.getItem('website_url') || '';
if (cachedData && cachedUrl === finalUserUrl && cacheTimestamp) {
const cacheAge = Date.now() - parseInt(cacheTimestamp);
const cacheValidDuration = 24 * 60 * 60 * 1000; // 24 hours
// Check if cache is still valid (less than 24 hours old)
if (cacheAge < cacheValidDuration) {
const parsedData = JSON.parse(cachedData);
console.log('CompetitorAnalysisStep: Loading cached competitor analysis:', {
url: cachedUrl,
cacheAge: Math.round(cacheAge / (60 * 1000)),
competitors: parsedData.competitors?.length || 0
});
setCompetitors(parsedData.competitors || []);
setSocialMediaAccounts(parsedData.social_media_accounts || {});
setSocialMediaCitations(parsedData.social_media_citations || []);
setResearchSummary(parsedData.research_summary || null);
setUsingCachedData(true);
return true; // Successfully loaded from cache
} else {
console.log('CompetitorAnalysisStep: Cache expired, will run fresh analysis');
}
}
return false; // No valid cache found
} catch (err) {
console.error('Error loading cached analysis:', err);
return false;
}
}, [userUrl]);
const startCompetitorDiscovery = useCallback(async (force = false) => {
// Check cache first unless forced
if (!force && loadCachedAnalysis()) {
console.log('CompetitorAnalysisStep: Using cached competitor analysis');
return;
}
const startCompetitorDiscovery = useCallback(async () => {
setIsAnalyzing(true);
setShowProgressModal(true);
setError(null);
setAnalysisProgress(0);
setAnalysisStep('Initializing competitor discovery...');
setUsingCachedData(false);
try {
setAnalysisStep('Validating session...');
@@ -139,10 +190,28 @@ const CompetitorAnalysisStep: React.FC<CompetitorAnalysisStepProps> = ({
setAnalysisProgress(100);
await new Promise(resolve => setTimeout(resolve, 500));
setCompetitors(result.competitors || []);
setSocialMediaAccounts(result.social_media_accounts || {});
setSocialMediaCitations(result.social_media_citations || []);
setResearchSummary(result.research_summary || null);
const analysisData = {
competitors: result.competitors || [],
social_media_accounts: result.social_media_accounts || {},
social_media_citations: result.social_media_citations || [],
research_summary: result.research_summary || null
};
setCompetitors(analysisData.competitors);
setSocialMediaAccounts(analysisData.social_media_accounts);
setSocialMediaCitations(analysisData.social_media_citations);
setResearchSummary(analysisData.research_summary);
// Cache the analysis results
try {
localStorage.setItem('competitor_analysis_data', JSON.stringify(analysisData));
localStorage.setItem('competitor_analysis_url', finalUserUrl);
localStorage.setItem('competitor_analysis_timestamp', Date.now().toString());
console.log('CompetitorAnalysisStep: Cached competitor analysis for future use');
} catch (cacheErr) {
console.warn('Failed to cache competitor analysis:', cacheErr);
}
setShowProgressModal(false);
setIsAnalyzing(false);
} else {
@@ -154,11 +223,23 @@ const CompetitorAnalysisStep: React.FC<CompetitorAnalysisStepProps> = ({
setIsAnalyzing(false);
setShowProgressModal(false);
}
}, [userUrl, industryContext]); // sessionId removed from dependencies
}, [userUrl, industryContext, loadCachedAnalysis]); // sessionId removed from dependencies
// Initialize: Check cache first, then run analysis if needed
useEffect(() => {
startCompetitorDiscovery();
}, [startCompetitorDiscovery]);
const initialize = async () => {
// Try to load from cache first
const cacheLoaded = loadCachedAnalysis();
// If no cache found, run fresh analysis
if (!cacheLoaded) {
await startCompetitorDiscovery(false);
}
};
initialize();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []); // Run only once on mount
const handleContinue = () => {
const researchData = {
@@ -180,20 +261,58 @@ const CompetitorAnalysisStep: React.FC<CompetitorAnalysisStepProps> = ({
return (
<Box sx={classes.container}>
<Box sx={classes.header}>
<Typography variant="h4" sx={{ fontWeight: 600, mb: 2 }}>
<Typography
variant="h4"
sx={{
fontWeight: 600,
mb: 2,
color: '#1a202c !important' // Force dark text for readability
}}
>
Research Your Competition
</Typography>
<Typography variant="h6" sx={{ color: 'text.secondary', fontWeight: 400 }}>
<Typography
variant="h6"
sx={{
color: '#4a5568 !important', // Force dark secondary text
fontWeight: 400
}}
>
Discover your competitors and analyze their strategies to gain competitive advantage
</Typography>
</Box>
{usingCachedData && !error && (
<Alert
severity="info"
sx={{
mb: 3,
background: 'linear-gradient(135deg, #e0f2fe 0%, #b3e5fc 100%)',
border: '1px solid #81d4fa',
color: '#01579b',
'& .MuiAlert-icon': {
color: '#0277bd'
}
}}
>
Loaded previously analyzed competitor data.
<Button
startIcon={<RefreshIcon />}
onClick={() => startCompetitorDiscovery(true)}
sx={{ ml: 2 }}
size="small"
>
Run Fresh Analysis
</Button>
</Alert>
)}
{error && (
<Alert severity="error" sx={{ mb: 3 }}>
{error}
<Button
startIcon={<RefreshIcon />}
onClick={startCompetitorDiscovery}
onClick={() => startCompetitorDiscovery(true)}
sx={{ ml: 2 }}
>
Retry
@@ -204,23 +323,36 @@ const CompetitorAnalysisStep: React.FC<CompetitorAnalysisStepProps> = ({
{!isAnalyzing && !error && (competitors.length > 0 || researchSummary) && (
<Box>
{researchSummary && (
<Paper sx={{ p: 3, mb: 4, backgroundColor: 'primary.50', border: '1px solid', borderColor: 'primary.200' }}>
<Paper sx={{
p: 3,
mb: 4,
background: 'linear-gradient(135deg, #e0f2fe 0%, #b3e5fc 100%)', // Warm sky-blue gradient
border: '1px solid #81d4fa',
borderRadius: 2,
boxShadow: '0 4px 12px rgba(3, 169, 244, 0.15)'
}}>
<Typography variant="h6" gutterBottom fontWeight={600} color="primary">
<AssessmentIcon sx={{ mr: 1, verticalAlign: 'middle' }} />
Research Summary
</Typography>
<Grid container spacing={3} mt={1}>
<Grid item xs={12} md={3}>
<Grid item xs={12} sm={6} md={3}>
<Typography variant="h4" color="primary" fontWeight={700}>
{researchSummary.total_competitors}
</Typography>
<Typography variant="body2" color="text.secondary">
<Typography
variant="body2"
sx={{ color: '#4a5568 !important' }} // Force dark text for readability
>
Competitors Found
</Typography>
</Grid>
<Grid item xs={12} md={9}>
<Typography variant="body1" color="text.secondary">
<Grid item xs={12} sm={6} md={9}>
<Typography
variant="body1"
sx={{ color: '#2d3748 !important' }} // Force dark text for readability
>
{researchSummary.market_insights}
</Typography>
</Grid>
@@ -231,8 +363,14 @@ const CompetitorAnalysisStep: React.FC<CompetitorAnalysisStepProps> = ({
{/* Social Media Accounts Section */}
{Object.keys(socialMediaAccounts).length > 0 && (
<>
<Typography variant="h6" gutterBottom fontWeight={600} mb={3}>
<ShareIcon sx={{ mr: 1, verticalAlign: 'middle' }} />
<Typography
variant="h6"
gutterBottom
fontWeight={600}
mb={3}
sx={{ color: '#1a202c !important' }} // Force dark text
>
<ShareIcon sx={{ mr: 1, verticalAlign: 'middle', color: '#667eea !important' }} />
Social Media Presence
</Typography>
@@ -250,8 +388,18 @@ const CompetitorAnalysisStep: React.FC<CompetitorAnalysisStepProps> = ({
};
return (
<Grid item xs={12} sm={6} md={4} key={platform}>
<Card sx={{ height: '100%' }}>
<Grid item xs={12} sm={6} md={4} lg={3} xl={2} key={platform}>
<Card sx={{
height: '100%',
background: 'linear-gradient(135deg, #e0f2fe 0%, #b3e5fc 100%)',
border: '1px solid #81d4fa',
boxShadow: '0 4px 12px rgba(3, 169, 244, 0.15)',
transition: 'all 0.3s ease',
'&:hover': {
transform: 'translateY(-4px)',
boxShadow: '0 8px 20px rgba(3, 169, 244, 0.25)'
}
}}>
<CardContent>
<Box display="flex" alignItems="center" gap={2}>
<Avatar sx={{ width: 40, height: 40, bgcolor: 'primary.main' }}>
@@ -282,25 +430,52 @@ const CompetitorAnalysisStep: React.FC<CompetitorAnalysisStepProps> = ({
</>
)}
<Typography variant="h6" gutterBottom fontWeight={600} mb={3}>
<BusinessIcon sx={{ mr: 1, verticalAlign: 'middle' }} />
<Typography
variant="h6"
gutterBottom
fontWeight={600}
mb={3}
sx={{ color: '#1a202c !important' }} // Force dark text
>
<BusinessIcon sx={{ mr: 1, verticalAlign: 'middle', color: '#667eea !important' }} />
Discovered Competitors ({competitors.length})
</Typography>
<Grid container spacing={3}>
{competitors.map((competitor, index) => (
<Grid item xs={12} md={6} lg={4} key={index}>
<Card sx={{ height: '100%', display: 'flex', flexDirection: 'column' }}>
<Grid item xs={12} sm={6} md={4} lg={3} xl={2} key={index}>
<Card sx={{
height: '100%',
display: 'flex',
flexDirection: 'column',
background: 'linear-gradient(135deg, #e0f2fe 0%, #b3e5fc 100%)',
border: '1px solid #81d4fa',
boxShadow: '0 4px 12px rgba(3, 169, 244, 0.15)',
transition: 'all 0.3s ease',
'&:hover': {
transform: 'translateY(-4px)',
boxShadow: '0 8px 20px rgba(3, 169, 244, 0.25)'
}
}}>
<CardContent sx={{ flexGrow: 1 }}>
<Box display="flex" alignItems="flex-start" gap={2} mb={2}>
<Avatar sx={{ width: 40, height: 40 }}>
<BusinessIcon />
</Avatar>
<Box flex={1}>
<Typography variant="h6" fontWeight={600} gutterBottom>
<Typography
variant="h6"
fontWeight={600}
gutterBottom
sx={{ color: '#1a202c !important' }} // Force dark text for readability
>
{competitor.title}
</Typography>
<Typography variant="body2" color="text.secondary" gutterBottom>
<Typography
variant="body2"
gutterBottom
sx={{ color: '#4a5568 !important' }} // Force dark text for readability
>
{competitor.domain}
</Typography>
<Chip
@@ -311,7 +486,11 @@ const CompetitorAnalysisStep: React.FC<CompetitorAnalysisStepProps> = ({
</Box>
</Box>
<Typography variant="body2" color="text.secondary" mb={2}>
<Typography
variant="body2"
mb={2}
sx={{ color: '#2d3748 !important' }} // Force dark text for readability
>
{competitor.summary.length > 150
? `${competitor.summary.substring(0, 150)}...`
: competitor.summary

View File

@@ -8,27 +8,17 @@ import {
Alert,
CircularProgress,
Card,
CardContent,
Grid,
Dialog,
DialogTitle,
DialogContent,
DialogActions,
DialogContentText,
Fade,
LinearProgress,
Stepper,
Step,
StepLabel,
Checkbox,
FormControlLabel
DialogContentText
} from '@mui/material';
import {
Analytics as AnalyticsIcon,
History as HistoryIcon,
Business as BusinessIcon,
Star as StarIcon,
Verified as VerifiedIcon
Business as BusinessIcon
} from '@mui/icons-material';
// Extracted components
@@ -37,7 +27,6 @@ import { AnalysisResultsDisplay, AnalysisProgressDisplay } from './WebsiteStep/c
// Extracted utilities
import {
fixUrlFormat,
extractDomainName,
checkExistingAnalysis,
loadExistingAnalysis,
performAnalysis,
@@ -336,18 +325,17 @@ const WebsiteStep: React.FC<WebsiteStepProps> = ({ onContinue, updateHeaderConte
return;
}
const stepData = {
website: fixedUrl,
domainName: result.domainName || domainName,
analysis: result.analysis,
useAnalysisForGenAI,
};
// Set the loaded analysis data for display
setDomainName(result.domainName || domainName);
setAnalysis(result.analysis);
setSuccess('Previous analysis loaded successfully!');
// Store in localStorage for Step 3 (Competitor Analysis)
localStorage.setItem('website_url', fixedUrl);
localStorage.setItem('website_analysis_data', JSON.stringify(result.analysis));
onContinue(stepData);
// DO NOT call onContinue() here - let user review the analysis first
// User will click "Continue" button when ready to proceed
};
const handleNewAnalysis = async () => {

View File

@@ -14,22 +14,15 @@ import {
Checkbox,
FormControlLabel,
Alert,
Paper,
Tooltip
Paper
} from '@mui/material';
import {
AutoAwesome as AutoAwesomeIcon,
Verified as VerifiedIcon,
Psychology as PsychologyIcon,
Analytics as AnalyticsIcon,
TrendingUp as TrendingUpIcon,
Language as LanguageIcon,
Palette as PaletteIcon,
Speed as SpeedIcon,
Group as GroupIcon,
Business as BusinessIcon,
Lightbulb as LightbulbIcon,
Warning as WarningIcon
Lightbulb as LightbulbIcon
} from '@mui/icons-material';
// Import rendering utilities
@@ -45,7 +38,12 @@ import {
} from '../utils/renderUtils';
// Import extracted components
import { EnhancedGuidelinesSection, KeyInsightsGrid } from './index';
import {
EnhancedGuidelinesSection,
KeyInsightsGrid,
ContentCharacteristicsSection,
TargetAudienceAnalysisSection
} from './index';
import { useOnboardingStyles } from '../../common/useOnboardingStyles';
interface StyleAnalysis {
@@ -169,10 +167,24 @@ const AnalysisResultsDisplay: React.FC<AnalysisResultsDisplayProps> = ({
<Box sx={styles.analysisHeader}>
<VerifiedIcon sx={styles.analysisHeaderIcon} />
<Box>
<Typography variant="h4" sx={styles.analysisHeaderTitle} gutterBottom>
<Typography
variant="h4"
sx={{
...styles.analysisHeaderTitle,
color: '#1a202c !important', // Force dark text
fontWeight: '700 !important'
}}
gutterBottom
>
{domainName} Style Analysis
</Typography>
<Typography variant="body1" sx={styles.analysisHeaderSubtitle}>
<Typography
variant="body1"
sx={{
...styles.analysisHeaderSubtitle,
color: '#4a5568 !important' // Force dark secondary text
}}
>
Comprehensive content analysis and personalized recommendations
</Typography>
</Box>
@@ -186,253 +198,32 @@ const AnalysisResultsDisplay: React.FC<AnalysisResultsDisplayProps> = ({
/>
{/* Content Characteristics Section */}
{analysis.content_characteristics && (
<Box sx={styles.analysisSection}>
<Typography variant="h5" sx={styles.analysisSectionHeader} gutterBottom>
<AnalyticsIcon color="info" />
Content Characteristics
</Typography>
<Grid container spacing={2}>
{analysis.content_characteristics.vocabulary_level && (
<Grid item xs={12} md={6}>
<Tooltip title="The complexity and sophistication of words used in the content. Higher levels use more advanced vocabulary while accessible levels use simpler, everyday words." arrow>
<Box>
{renderKeyInsight(
'Vocabulary Level',
analysis.content_characteristics.vocabulary_level,
<LanguageIcon />,
'info'
)}
</Box>
</Tooltip>
</Grid>
)}
{analysis.content_characteristics.readability_score && (
<Grid item xs={12} md={6}>
<Tooltip title="How easy it is for readers to understand the content. Higher scores mean the content is easier to read and comprehend." arrow>
<Box>
{renderKeyInsight(
'Readability Score',
analysis.content_characteristics.readability_score,
<SpeedIcon />,
'success'
)}
</Box>
</Tooltip>
</Grid>
)}
{analysis.content_characteristics.content_density && (
<Grid item xs={12} md={6}>
<Tooltip title="How much information is packed into each section. Moderate density balances information with readability." arrow>
<Box>
{renderKeyInsight(
'Content Density',
analysis.content_characteristics.content_density,
<PaletteIcon />,
'warning'
)}
</Box>
</Tooltip>
</Grid>
)}
{analysis.content_characteristics.sentence_structure && (
<Grid item xs={12} md={6}>
<Tooltip title="The variety and complexity of sentence patterns used. Varied structures keep readers engaged." arrow>
<Box>
{renderKeyInsight(
'Sentence Structure',
analysis.content_characteristics.sentence_structure,
<AnalyticsIcon />,
'secondary'
)}
</Box>
</Tooltip>
</Grid>
)}
{analysis.content_characteristics.paragraph_organization && (
<Grid item xs={12} md={6}>
<Tooltip title="How paragraphs are structured and organized. Clear organization helps readers follow the content easily." arrow>
<Box>
{renderKeyInsight(
'Paragraph Organization',
analysis.content_characteristics.paragraph_organization,
<AnalyticsIcon />,
'primary'
)}
</Box>
</Tooltip>
</Grid>
)}
{analysis.content_characteristics.content_flow && (
<Grid item xs={12} md={6}>
<Tooltip title="How smoothly the content moves from one idea to the next. Good flow keeps readers engaged throughout." arrow>
<Box>
{renderKeyInsight(
'Content Flow',
analysis.content_characteristics.content_flow,
<TrendingUpIcon />,
'success'
)}
</Box>
</Tooltip>
</Grid>
)}
{analysis.content_characteristics.visual_elements_usage && (
<Grid item xs={12} md={6}>
<Tooltip title="How often images, charts, and other visual elements are used to support the text content." arrow>
<Box>
{renderKeyInsight(
'Visual Elements Usage',
analysis.content_characteristics.visual_elements_usage,
<PaletteIcon />,
'warning'
)}
</Box>
</Tooltip>
</Grid>
)}
</Grid>
</Box>
)}
<ContentCharacteristicsSection
contentCharacteristics={analysis.content_characteristics as any}
/>
{/* Detailed Target Audience Section */}
{analysis.target_audience && (
<Box sx={styles.analysisSection}>
<Typography variant="h5" sx={styles.analysisSectionHeader} gutterBottom>
<GroupIcon color="info" />
Target Audience Analysis
</Typography>
<Grid container spacing={2}>
{analysis.target_audience.demographics && analysis.target_audience.demographics.length > 0 && (
<Grid item xs={12} md={6}>
{renderKeyInsight(
'Demographics',
analysis.target_audience.demographics,
<GroupIcon />,
'info'
)}
</Grid>
)}
{analysis.target_audience.industry_focus && (
<Grid item xs={12} md={6}>
{renderKeyInsight(
'Industry Focus',
analysis.target_audience.industry_focus,
<BusinessIcon />,
'primary'
)}
</Grid>
)}
{analysis.target_audience.geographic_focus && (
<Grid item xs={12} md={6}>
{renderKeyInsight(
'Geographic Focus',
analysis.target_audience.geographic_focus,
<AnalyticsIcon />,
'secondary'
)}
</Grid>
)}
{analysis.target_audience.psychographic_profile && (
<Grid item xs={12} md={6}>
<Paper elevation={2} sx={styles.analysisAccentPaperSuccess}>
<Box display="flex" alignItems="center" gap={2}>
<Box sx={styles.analysisAccentIconSuccess}>
<PsychologyIcon />
</Box>
<Box flex={1}>
<Typography variant="subtitle2" color="textSecondary" gutterBottom>
Psychographic Profile
</Typography>
<Box component="ul" sx={styles.analysisList}>
{Array.isArray(analysis.target_audience.psychographic_profile)
? analysis.target_audience.psychographic_profile.map((item: string, index: number) => (
<Typography component="li" variant="body2" key={index} sx={styles.analysisListItem}>
{item}
</Typography>
))
: (
<Typography component="li" variant="body2" sx={styles.analysisListItem}>
{analysis.target_audience.psychographic_profile}
</Typography>
)}
</Box>
</Box>
</Box>
</Paper>
</Grid>
)}
{analysis.target_audience.pain_points && analysis.target_audience.pain_points.length > 0 && (
<Grid item xs={12} md={6}>
<Paper elevation={2} sx={styles.analysisAccentPaperError}>
<Box display="flex" alignItems="center" gap={2}>
<Box sx={styles.analysisAccentIconError}>
<WarningIcon />
</Box>
<Box flex={1}>
<Typography variant="subtitle2" color="textSecondary" gutterBottom>
Pain Points
</Typography>
<Box component="ul" sx={styles.analysisList}>
{analysis.target_audience.pain_points.map((painPoint: string, index: number) => (
<Typography component="li" variant="body2" key={index} sx={styles.analysisListItem}>
{painPoint}
</Typography>
))}
</Box>
</Box>
</Box>
</Paper>
</Grid>
)}
{analysis.target_audience.motivations && analysis.target_audience.motivations.length > 0 && (
<Grid item xs={12} md={6}>
<Paper elevation={2} sx={styles.analysisAccentPaperSuccess}>
<Box display="flex" alignItems="center" gap={2}>
<Box sx={styles.analysisAccentIconSuccess}>
<TrendingUpIcon />
</Box>
<Box flex={1}>
<Typography variant="subtitle2" color="textSecondary" gutterBottom>
Motivations
</Typography>
<Box component="ul" sx={styles.analysisList}>
{analysis.target_audience.motivations.map((motivation: string, index: number) => (
<Typography component="li" variant="body2" key={index} sx={styles.analysisListItem}>
{motivation}
</Typography>
))}
</Box>
</Box>
</Box>
</Paper>
</Grid>
)}
</Grid>
</Box>
)}
{/* Target Audience Analysis Section */}
<TargetAudienceAnalysisSection
targetAudience={analysis.target_audience as any}
/>
{/* Content Type Details Section */}
{analysis.content_type && (
<Box sx={styles.analysisSection}>
<Typography variant="h5" sx={styles.analysisSectionHeader} gutterBottom>
<BusinessIcon color="primary" />
<Box sx={{ ...styles.analysisSection, mt: 4 }}>
<Typography
variant="h5"
sx={{
...styles.analysisSectionHeader,
color: '#1a202c !important', // Force dark text
fontWeight: '700 !important'
}}
>
<BusinessIcon sx={{ color: '#667eea !important' }} />
Content Type Analysis
</Typography>
<Grid container spacing={2}>
{analysis.content_type.purpose && (
<Grid item xs={12} md={6}>
<Grid item xs={12} sm={6} md={4} lg={3} xl={2}>
{renderKeyInsight(
'Content Purpose',
analysis.content_type.purpose,
@@ -443,7 +234,7 @@ const AnalysisResultsDisplay: React.FC<AnalysisResultsDisplayProps> = ({
)}
{analysis.content_type.call_to_action && (
<Grid item xs={12} md={6}>
<Grid item xs={12} sm={6} md={4} lg={3} xl={2}>
{renderKeyInsight(
'Call to Action Style',
analysis.content_type.call_to_action,
@@ -454,7 +245,7 @@ const AnalysisResultsDisplay: React.FC<AnalysisResultsDisplayProps> = ({
)}
{analysis.content_type.conversion_focus && (
<Grid item xs={12} md={6}>
<Grid item xs={12} sm={6} md={4} lg={3} xl={2}>
{renderKeyInsight(
'Conversion Focus',
analysis.content_type.conversion_focus,
@@ -465,7 +256,7 @@ const AnalysisResultsDisplay: React.FC<AnalysisResultsDisplayProps> = ({
)}
{analysis.content_type.educational_value && (
<Grid item xs={12} md={6}>
<Grid item xs={12} sm={6} md={4} lg={3} xl={2}>
{renderKeyInsight(
'Educational Value',
analysis.content_type.educational_value,
@@ -507,7 +298,15 @@ const AnalysisResultsDisplay: React.FC<AnalysisResultsDisplayProps> = ({
{/* Content Strategy */}
{analysis.content_strategy && (
<Box sx={styles.analysisSection}>
<Typography variant="h5" sx={styles.analysisSectionHeader} gutterBottom>
<Typography
variant="h5"
sx={{
...styles.analysisSectionHeader,
color: '#1a202c !important', // Force dark text
fontWeight: '700 !important'
}}
gutterBottom
>
<AutoAwesomeIcon color="primary" />
Content Strategy
</Typography>
@@ -522,14 +321,22 @@ const AnalysisResultsDisplay: React.FC<AnalysisResultsDisplayProps> = ({
{/* Recommended Settings for AI Generation */}
{analysis.recommended_settings && (
<Box sx={styles.analysisSection}>
<Typography variant="h5" sx={styles.analysisSectionHeader} gutterBottom>
<Typography
variant="h5"
sx={{
...styles.analysisSectionHeader,
color: '#1a202c !important', // Force dark text
fontWeight: '700 !important'
}}
gutterBottom
>
<AutoAwesomeIcon color="primary" />
Recommended AI Generation Settings
</Typography>
<Paper elevation={3} sx={styles.analysisGradientPaperPrimary}>
<Grid container spacing={2}>
{analysis.recommended_settings.writing_tone && (
<Grid item xs={12} md={6}>
<Grid item xs={12} sm={6} md={4} lg={3} xl={2}>
<Typography variant="subtitle2" sx={styles.analysisSubheader}>
Writing Tone:
</Typography>
@@ -540,7 +347,7 @@ const AnalysisResultsDisplay: React.FC<AnalysisResultsDisplayProps> = ({
)}
{analysis.recommended_settings.target_audience && (
<Grid item xs={12} md={6}>
<Grid item xs={12} sm={6} md={4} lg={3} xl={2}>
<Typography variant="subtitle2" sx={styles.analysisSubheader}>
Target Audience:
</Typography>
@@ -551,7 +358,7 @@ const AnalysisResultsDisplay: React.FC<AnalysisResultsDisplayProps> = ({
)}
{analysis.recommended_settings.content_type && (
<Grid item xs={12} md={6}>
<Grid item xs={12} sm={6} md={4} lg={3} xl={2}>
<Typography variant="subtitle2" sx={styles.analysisSubheader}>
Content Type:
</Typography>
@@ -562,7 +369,7 @@ const AnalysisResultsDisplay: React.FC<AnalysisResultsDisplayProps> = ({
)}
{analysis.recommended_settings.creativity_level && (
<Grid item xs={12} md={6}>
<Grid item xs={12} sm={6} md={4} lg={3} xl={2}>
<Typography variant="subtitle2" sx={styles.analysisSubheader}>
Creativity Level:
</Typography>
@@ -573,7 +380,7 @@ const AnalysisResultsDisplay: React.FC<AnalysisResultsDisplayProps> = ({
)}
{analysis.recommended_settings.industry_context && (
<Grid item xs={12} md={6}>
<Grid item xs={12} sm={6} md={4} lg={3} xl={2}>
<Typography variant="subtitle2" sx={styles.analysisSubheader}>
Industry Context:
</Typography>
@@ -584,7 +391,7 @@ const AnalysisResultsDisplay: React.FC<AnalysisResultsDisplayProps> = ({
)}
{analysis.recommended_settings.geographic_location && (
<Grid item xs={12} md={6}>
<Grid item xs={12} sm={6} md={4} lg={3} xl={2}>
<Typography variant="subtitle2" sx={styles.analysisSubheader}>
Geographic Focus:
</Typography>
@@ -595,7 +402,7 @@ const AnalysisResultsDisplay: React.FC<AnalysisResultsDisplayProps> = ({
)}
{analysis.recommended_settings.brand_alignment && (
<Grid item xs={12} md={6}>
<Grid item xs={12} sm={6} md={4} lg={3} xl={2}>
<Typography variant="subtitle2" sx={styles.analysisSubheader}>
Brand Alignment:
</Typography>
@@ -628,7 +435,15 @@ const AnalysisResultsDisplay: React.FC<AnalysisResultsDisplayProps> = ({
{/* Style Consistency Section */}
{analysis.style_consistency && (
<Box sx={styles.analysisSection}>
<Typography variant="h5" sx={styles.analysisSectionHeader} gutterBottom>
<Typography
variant="h5"
sx={{
...styles.analysisSectionHeader,
color: '#1a202c !important', // Force dark text
fontWeight: '700 !important'
}}
gutterBottom
>
<AnalyticsIcon color="info" />
Style Consistency
</Typography>
@@ -643,7 +458,15 @@ const AnalysisResultsDisplay: React.FC<AnalysisResultsDisplayProps> = ({
{/* Unique Elements Section */}
{analysis.unique_elements && analysis.unique_elements.length > 0 && (
<Box sx={styles.analysisSection}>
<Typography variant="h5" sx={styles.analysisSectionHeader} gutterBottom>
<Typography
variant="h5"
sx={{
...styles.analysisSectionHeader,
color: '#1a202c !important', // Force dark text
fontWeight: '700 !important'
}}
gutterBottom
>
<AutoAwesomeIcon color="primary" />
Unique Style Elements
</Typography>
@@ -670,13 +493,13 @@ const AnalysisResultsDisplay: React.FC<AnalysisResultsDisplayProps> = ({
{/* Best Practices & Avoid Elements */}
<Grid container spacing={2} sx={styles.analysisSection}>
{analysis.best_practices && (
<Grid item xs={12} md={6}>
<Grid item xs={12} sm={6} md={4} lg={3} xl={2}>
{renderBestPracticesSection(analysis.best_practices)}
</Grid>
)}
{analysis.avoid_elements && (
<Grid item xs={12} md={6}>
<Grid item xs={12} sm={6} md={4} lg={3} xl={2}>
{renderAvoidElementsSection(analysis.avoid_elements)}
</Grid>
)}
@@ -685,7 +508,15 @@ const AnalysisResultsDisplay: React.FC<AnalysisResultsDisplayProps> = ({
{/* Competitive Advantages */}
{analysis.competitive_advantages && analysis.competitive_advantages.length > 0 && (
<Box sx={styles.analysisSection}>
<Typography variant="h5" sx={styles.analysisSectionHeader} gutterBottom>
<Typography
variant="h5"
sx={{
...styles.analysisSectionHeader,
color: '#1a202c !important', // Force dark text
fontWeight: '700 !important'
}}
gutterBottom
>
<TrendingUpIcon color="success" />
Competitive Advantages
</Typography>
@@ -704,7 +535,15 @@ const AnalysisResultsDisplay: React.FC<AnalysisResultsDisplayProps> = ({
{/* Content Calendar Suggestions */}
{analysis.content_calendar_suggestions && analysis.content_calendar_suggestions.length > 0 && (
<Box sx={styles.analysisSection}>
<Typography variant="h5" sx={styles.analysisSectionHeader} gutterBottom>
<Typography
variant="h5"
sx={{
...styles.analysisSectionHeader,
color: '#1a202c !important', // Force dark text
fontWeight: '700 !important'
}}
gutterBottom
>
<AnalyticsIcon color="primary" />
Content Calendar Suggestions
</Typography>
@@ -720,6 +559,56 @@ const AnalysisResultsDisplay: React.FC<AnalysisResultsDisplayProps> = ({
</Box>
)}
{/* Content Strategy */}
{analysis.content_strategy && (
<Box sx={styles.analysisSection}>
<Typography
variant="h5"
sx={{
...styles.analysisSectionHeader,
color: '#1a202c !important', // Force dark text
fontWeight: '700 !important'
}}
gutterBottom
>
<BusinessIcon color="primary" />
Content Strategy Overview
</Typography>
<Paper elevation={3} sx={styles.analysisGradientPaperPrimary}>
<Typography variant="body1" sx={styles.analysisParagraph}>
{analysis.content_strategy}
</Typography>
</Paper>
</Box>
)}
{/* AI Generation Tips */}
{analysis.ai_generation_tips && analysis.ai_generation_tips.length > 0 && (
<Box sx={styles.analysisSection}>
<Typography
variant="h5"
sx={{
...styles.analysisSectionHeader,
color: '#1a202c !important', // Force dark text
fontWeight: '700 !important'
}}
gutterBottom
>
<AutoAwesomeIcon color="secondary" />
AI Content Generation Tips
</Typography>
<Paper elevation={3} sx={styles.analysisGradientPaperAccent}>
<Box component="ul" sx={styles.analysisList}>
{analysis.ai_generation_tips.map((tip: string, index: number) => (
<Typography component="li" variant="body1" key={index} sx={styles.analysisListItem}>
{tip}
</Typography>
))}
</Box>
</Paper>
</Box>
)}
{/* GenAI Integration Checkbox */}
<Box sx={styles.analysisCheckboxContainer}>
<FormControlLabel

View File

@@ -0,0 +1,171 @@
/**
* Content Characteristics Section Component
* Displays content characteristics analysis in a reusable format
*/
import React from 'react';
import {
Box,
Typography,
Grid,
Tooltip
} from '@mui/material';
import {
Analytics as AnalyticsIcon,
Language as LanguageIcon,
Speed as SpeedIcon,
Palette as PaletteIcon,
TrendingUp as TrendingUpIcon
} from '@mui/icons-material';
import { renderKeyInsight } from '../utils/renderUtils';
import { useOnboardingStyles } from '../../common/useOnboardingStyles';
interface ContentCharacteristics {
sentence_structure?: string;
vocabulary_level?: string;
paragraph_organization?: string;
content_flow?: string;
readability_score?: string;
content_density?: string;
visual_elements_usage?: string;
}
interface ContentCharacteristicsSectionProps {
contentCharacteristics?: ContentCharacteristics;
}
const ContentCharacteristicsSection: React.FC<ContentCharacteristicsSectionProps> = ({
contentCharacteristics
}) => {
const styles = useOnboardingStyles();
if (!contentCharacteristics) {
return null;
}
return (
<Box sx={{ ...styles.analysisSection, mt: 4 }}>
<Typography
variant="h5"
sx={{
...styles.analysisSectionHeader,
color: '#1a202c !important', // Force dark text
fontWeight: '700 !important'
}}
>
<AnalyticsIcon sx={{ color: '#667eea !important' }} />
Content Characteristics
</Typography>
<Grid container spacing={2}>
{contentCharacteristics.vocabulary_level && (
<Grid item xs={12} sm={6} md={4} lg={3} xl={2}>
<Tooltip title="The complexity and sophistication of words used in the content. Higher levels use more advanced vocabulary while accessible levels use simpler, everyday words." arrow>
<Box>
{renderKeyInsight(
'Vocabulary Level',
contentCharacteristics.vocabulary_level,
<LanguageIcon />,
'info'
)}
</Box>
</Tooltip>
</Grid>
)}
{contentCharacteristics.readability_score && (
<Grid item xs={12} sm={6} md={4} lg={3} xl={2}>
<Tooltip title="How easy it is for readers to understand the content. Higher scores mean the content is easier to read and comprehend." arrow>
<Box>
{renderKeyInsight(
'Readability Score',
contentCharacteristics.readability_score,
<SpeedIcon />,
'success'
)}
</Box>
</Tooltip>
</Grid>
)}
{contentCharacteristics.content_density && (
<Grid item xs={12} sm={6} md={4} lg={3} xl={2}>
<Tooltip title="How much information is packed into each section. Moderate density balances information with readability." arrow>
<Box>
{renderKeyInsight(
'Content Density',
contentCharacteristics.content_density,
<PaletteIcon />,
'warning'
)}
</Box>
</Tooltip>
</Grid>
)}
{contentCharacteristics.sentence_structure && (
<Grid item xs={12} sm={6} md={4} lg={3} xl={2}>
<Tooltip title="The variety and complexity of sentence patterns used. Varied structures keep readers engaged." arrow>
<Box>
{renderKeyInsight(
'Sentence Structure',
contentCharacteristics.sentence_structure,
<AnalyticsIcon />,
'secondary'
)}
</Box>
</Tooltip>
</Grid>
)}
{contentCharacteristics.paragraph_organization && (
<Grid item xs={12} sm={6} md={4} lg={3} xl={2}>
<Tooltip title="How paragraphs are structured and organized. Clear organization helps readers follow the content easily." arrow>
<Box>
{renderKeyInsight(
'Paragraph Organization',
contentCharacteristics.paragraph_organization,
<AnalyticsIcon />,
'primary'
)}
</Box>
</Tooltip>
</Grid>
)}
{contentCharacteristics.content_flow && (
<Grid item xs={12} sm={6} md={4} lg={3} xl={2}>
<Tooltip title="How smoothly the content moves from one idea to the next. Good flow keeps readers engaged throughout." arrow>
<Box>
{renderKeyInsight(
'Content Flow',
contentCharacteristics.content_flow,
<TrendingUpIcon />,
'success'
)}
</Box>
</Tooltip>
</Grid>
)}
{contentCharacteristics.visual_elements_usage && (
<Grid item xs={12} sm={6} md={4} lg={3} xl={2}>
<Tooltip title="How often images, charts, and other visual elements are used to support the text content." arrow>
<Box>
{renderKeyInsight(
'Visual Elements Usage',
contentCharacteristics.visual_elements_usage,
<PaletteIcon />,
'warning'
)}
</Box>
</Tooltip>
</Grid>
)}
</Grid>
</Box>
);
};
export default ContentCharacteristicsSection;

View File

@@ -56,7 +56,7 @@ const KeyInsightsGrid: React.FC<KeyInsightsGridProps> = ({
return (
<Grid container spacing={2} sx={{ mb: 2.5 }}>
{writing_style?.tone && (
<Grid item xs={12} md={6}>
<Grid item xs={12} sm={6} md={4} lg={3} xl={2}>
<Tooltip title="The emotional quality and attitude of the writing - how it makes readers feel and the mood it creates." arrow>
<Box>
{renderKeyInsight(
@@ -71,7 +71,7 @@ const KeyInsightsGrid: React.FC<KeyInsightsGridProps> = ({
)}
{writing_style?.complexity && (
<Grid item xs={12} md={6}>
<Grid item xs={12} sm={6} md={4} lg={3} xl={2}>
<Tooltip title="How sophisticated or simple the content is. Moderate complexity balances depth with accessibility." arrow>
<Box>
{renderKeyInsight(
@@ -86,7 +86,7 @@ const KeyInsightsGrid: React.FC<KeyInsightsGridProps> = ({
)}
{writing_style?.voice && (
<Grid item xs={12} md={6}>
<Grid item xs={12} sm={6} md={4} lg={3} xl={2}>
<Tooltip title="The unique personality and style of the writing - what makes it distinctive and recognizable." arrow>
<Box>
{renderKeyInsight(
@@ -101,7 +101,7 @@ const KeyInsightsGrid: React.FC<KeyInsightsGridProps> = ({
)}
{writing_style?.engagement_level && (
<Grid item xs={12} md={6}>
<Grid item xs={12} sm={6} md={4} lg={3} xl={2}>
<Tooltip title="How well the content captures and maintains reader attention throughout the piece." arrow>
<Box>
{renderKeyInsight(
@@ -116,7 +116,7 @@ const KeyInsightsGrid: React.FC<KeyInsightsGridProps> = ({
)}
{writing_style?.brand_personality && (
<Grid item xs={12} md={6}>
<Grid item xs={12} sm={6} md={4} lg={3} xl={2}>
<Tooltip title="The human characteristics and traits associated with the brand, like friendly, professional, or innovative." arrow>
<Box>
{renderKeyInsight(
@@ -131,7 +131,7 @@ const KeyInsightsGrid: React.FC<KeyInsightsGridProps> = ({
)}
{writing_style?.formality_level && (
<Grid item xs={12} md={6}>
<Grid item xs={12} sm={6} md={4} lg={3} xl={2}>
<Tooltip title="How formal or casual the writing style is. Semi-formal strikes a balance between professional and approachable." arrow>
<Box>
{renderKeyInsight(
@@ -146,7 +146,7 @@ const KeyInsightsGrid: React.FC<KeyInsightsGridProps> = ({
)}
{writing_style?.emotional_appeal && (
<Grid item xs={12} md={6}>
<Grid item xs={12} sm={6} md={4} lg={3} xl={2}>
<Tooltip title="How the content connects with readers' emotions - what feelings it aims to evoke." arrow>
<Box>
{renderKeyInsight(
@@ -161,7 +161,7 @@ const KeyInsightsGrid: React.FC<KeyInsightsGridProps> = ({
)}
{target_audience?.expertise_level && (
<Grid item xs={12} md={6}>
<Grid item xs={12} sm={6} md={4} lg={3} xl={2}>
<Tooltip title="The skill level and experience of the intended readers - from beginners to experts in the subject matter." arrow>
<Box>
{renderKeyInsight(
@@ -176,7 +176,7 @@ const KeyInsightsGrid: React.FC<KeyInsightsGridProps> = ({
)}
{target_audience?.geographic_focus && target_audience.geographic_focus.trim() !== '' && (
<Grid item xs={12} md={6}>
<Grid item xs={12} sm={6} md={4} lg={3} xl={2}>
<Tooltip title="The geographical regions or areas the content is primarily intended for - local, national, or global reach." arrow>
<Box>
{renderKeyInsight(
@@ -191,7 +191,7 @@ const KeyInsightsGrid: React.FC<KeyInsightsGridProps> = ({
)}
{content_type?.primary_type && (
<Grid item xs={12} md={6}>
<Grid item xs={12} sm={6} md={4} lg={3} xl={2}>
<Tooltip title="The main category or format of content being created - blog posts, tutorials, product descriptions, etc." arrow>
<Box>
{renderKeyInsight(

View File

@@ -0,0 +1,178 @@
/**
* Target Audience Analysis Section Component
* Displays target audience analysis in a reusable format
*/
import React from 'react';
import {
Box,
Typography,
Grid,
Paper
} from '@mui/material';
import {
Group as GroupIcon,
Business as BusinessIcon,
Analytics as AnalyticsIcon,
Psychology as PsychologyIcon,
Warning as WarningIcon,
TrendingUp as TrendingUpIcon
} from '@mui/icons-material';
import { renderKeyInsight } from '../utils/renderUtils';
import { useOnboardingStyles } from '../../common/useOnboardingStyles';
interface TargetAudience {
demographics?: string[];
expertise_level?: string;
industry_focus?: string;
geographic_focus?: string;
psychographic_profile?: string;
pain_points?: string[];
motivations?: string[];
}
interface TargetAudienceAnalysisSectionProps {
targetAudience?: TargetAudience;
}
const TargetAudienceAnalysisSection: React.FC<TargetAudienceAnalysisSectionProps> = ({
targetAudience
}) => {
const styles = useOnboardingStyles();
if (!targetAudience) {
return null;
}
return (
<Box sx={{ ...styles.analysisSection, mt: 4 }}>
<Typography
variant="h5"
sx={{
...styles.analysisSectionHeader,
color: '#1a202c !important', // Force dark text
fontWeight: '700 !important'
}}
>
<GroupIcon sx={{ color: '#667eea !important' }} />
Target Audience Analysis
</Typography>
<Grid container spacing={2}>
{targetAudience.demographics && targetAudience.demographics.length > 0 && (
<Grid item xs={12} sm={6} md={4} lg={3} xl={2}>
{renderKeyInsight(
'Demographics',
targetAudience.demographics,
<GroupIcon />,
'info'
)}
</Grid>
)}
{targetAudience.industry_focus && (
<Grid item xs={12} sm={6} md={4} lg={3} xl={2}>
{renderKeyInsight(
'Industry Focus',
targetAudience.industry_focus,
<BusinessIcon />,
'primary'
)}
</Grid>
)}
{targetAudience.geographic_focus && (
<Grid item xs={12} sm={6} md={4} lg={3} xl={2}>
{renderKeyInsight(
'Geographic Focus',
targetAudience.geographic_focus,
<AnalyticsIcon />,
'secondary'
)}
</Grid>
)}
{targetAudience.psychographic_profile && (
<Grid item xs={12} sm={6} md={4} lg={3} xl={2}>
<Paper elevation={2} sx={styles.analysisAccentPaperSuccess}>
<Box display="flex" alignItems="center" gap={2}>
<Box sx={styles.analysisAccentIconSuccess}>
<PsychologyIcon />
</Box>
<Box flex={1}>
<Typography variant="subtitle2" color="textSecondary" gutterBottom>
Psychographic Profile
</Typography>
<Box component="ul" sx={styles.analysisList}>
{Array.isArray(targetAudience.psychographic_profile)
? targetAudience.psychographic_profile.map((item: string, index: number) => (
<Typography component="li" variant="body2" key={index} sx={styles.analysisListItem}>
{item}
</Typography>
))
: (
<Typography component="li" variant="body2" sx={styles.analysisListItem}>
{targetAudience.psychographic_profile}
</Typography>
)}
</Box>
</Box>
</Box>
</Paper>
</Grid>
)}
{targetAudience.pain_points && targetAudience.pain_points.length > 0 && (
<Grid item xs={12} sm={6} md={4} lg={3} xl={2}>
<Paper elevation={2} sx={styles.analysisAccentPaperError}>
<Box display="flex" alignItems="center" gap={2}>
<Box sx={styles.analysisAccentIconError}>
<WarningIcon />
</Box>
<Box flex={1}>
<Typography variant="subtitle2" color="textSecondary" gutterBottom>
Pain Points
</Typography>
<Box component="ul" sx={styles.analysisList}>
{targetAudience.pain_points.map((painPoint: string, index: number) => (
<Typography component="li" variant="body2" key={index} sx={styles.analysisListItem}>
{painPoint}
</Typography>
))}
</Box>
</Box>
</Box>
</Paper>
</Grid>
)}
{targetAudience.motivations && targetAudience.motivations.length > 0 && (
<Grid item xs={12} sm={6} md={4} lg={3} xl={2}>
<Paper elevation={2} sx={styles.analysisAccentPaperSuccess}>
<Box display="flex" alignItems="center" gap={2}>
<Box sx={styles.analysisAccentIconSuccess}>
<TrendingUpIcon />
</Box>
<Box flex={1}>
<Typography variant="subtitle2" color="textSecondary" gutterBottom>
Motivations
</Typography>
<Box component="ul" sx={styles.analysisList}>
{targetAudience.motivations.map((motivation: string, index: number) => (
<Typography component="li" variant="body2" key={index} sx={styles.analysisListItem}>
{motivation}
</Typography>
))}
</Box>
</Box>
</Box>
</Paper>
</Grid>
)}
</Grid>
</Box>
);
};
export default TargetAudienceAnalysisSection;

View File

@@ -7,3 +7,5 @@ export { default as AnalysisResultsDisplay } from './AnalysisResultsDisplay';
export { default as AnalysisProgressDisplay } from './AnalysisProgressDisplay';
export { default as EnhancedGuidelinesSection } from './EnhancedGuidelinesSection';
export { default as KeyInsightsGrid } from './KeyInsightsGrid';
export { default as ContentCharacteristicsSection } from './ContentCharacteristicsSection';
export { default as TargetAudienceAnalysisSection } from './TargetAudienceAnalysisSection';

View File

@@ -20,6 +20,7 @@ import {
Zoom,
Divider
} from '@mui/material';
import { useTheme, alpha } from '@mui/material/styles';
import {
ExpandMore as ExpandMoreIcon,
CheckCircle as CheckIcon,
@@ -39,49 +40,120 @@ import {
} from '@mui/icons-material';
/**
* Renders a key insight card with icon and value
* Key Insight Card Component
*/
interface KeyInsightProps {
title: string;
value: string | string[];
icon: React.ReactNode;
color?: 'primary' | 'secondary' | 'success' | 'error' | 'warning' | 'info';
}
const KeyInsightCard: React.FC<KeyInsightProps> = ({
title,
value,
icon,
color = 'primary'
}) => {
const theme = useTheme();
const isDark = theme.palette.mode === 'dark';
// Helper function to safely get palette colors
const getPaletteColor = (colorKey: string) => {
const palette = theme.palette as any;
return palette[colorKey] || palette.primary;
};
const paletteColor = getPaletteColor(color);
return (
<Paper
elevation={0}
sx={{
p: 2.5,
mb: 0,
borderRadius: 2.5,
background: isDark
? `linear-gradient(135deg, ${alpha(paletteColor.main, 0.08)} 0%, ${alpha(paletteColor.main, 0.04)} 100%)`
: `linear-gradient(135deg, ${alpha(paletteColor.main, 0.06)} 0%, ${alpha(paletteColor.light, 0.08)} 100%)`,
border: `2px solid`,
borderColor: isDark
? alpha(paletteColor.main, 0.2)
: alpha(paletteColor.main, 0.15),
borderLeftWidth: '5px',
transition: 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)',
'&:hover': {
background: isDark
? `linear-gradient(135deg, ${alpha(paletteColor.main, 0.12)} 0%, ${alpha(paletteColor.main, 0.08)} 100%)`
: `linear-gradient(135deg, ${alpha(paletteColor.main, 0.10)} 0%, ${alpha(paletteColor.light, 0.12)} 100%)`,
borderColor: alpha(paletteColor.main, 0.4),
transform: 'translateY(-4px)',
boxShadow: isDark
? `0 12px 40px ${alpha(paletteColor.main, 0.2)}`
: `0 12px 40px ${alpha(paletteColor.main, 0.15)}`
}
}}
>
<Box display="flex" alignItems="center" gap={2}>
<Box
sx={{
color: `${color}.main`,
fontSize: '1.75rem',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
width: 48,
height: 48,
borderRadius: 2,
background: isDark
? alpha(paletteColor.main, 0.15)
: alpha(paletteColor.main, 0.1),
}}
>
{icon}
</Box>
<Box flex={1}>
<Typography
variant="caption"
sx={{
fontWeight: 700,
fontSize: '0.75rem',
letterSpacing: '0.5px',
textTransform: 'uppercase',
color: isDark ? '#ffffff !important' : '#000000 !important', // Maximum contrast
mb: 0.5,
display: 'block'
}}
>
{title}
</Typography>
<Typography
variant="body1"
sx={{
fontWeight: 600,
fontSize: '1.05rem',
color: isDark ? '#ffffff !important' : '#000000 !important', // Maximum contrast
lineHeight: 1.4
}}
>
{Array.isArray(value) ? value.join(', ') : value}
</Typography>
</Box>
</Box>
</Paper>
);
};
/**
* Backward-compatible wrapper function for renderKeyInsight
* @deprecated Use KeyInsightCard component directly instead
*/
export const renderKeyInsight = (
title: string,
value: string | string[],
icon: React.ReactNode,
color: string = 'primary'
) => (
<Paper
elevation={3}
sx={{
p: 2,
mb: 1.5,
borderRadius: 2,
background: 'linear-gradient(135deg, rgba(255, 255, 255, 0.08) 0%, rgba(255, 255, 255, 0.12) 100%)',
border: `1px solid rgba(255, 255, 255, 0.15)`,
borderLeft: `4px solid`,
borderLeftColor: `${color}.main`,
backdropFilter: 'blur(10px)',
transition: 'all 0.2s ease-in-out',
'&:hover': {
background: 'linear-gradient(135deg, rgba(255, 255, 255, 0.12) 0%, rgba(255, 255, 255, 0.16) 100%)',
border: `1px solid rgba(255, 255, 255, 0.25)`,
transform: 'translateY(-2px)',
boxShadow: '0 8px 25px rgba(0, 0, 0, 0.3)'
}
}}
>
<Box display="flex" alignItems="center" gap={2}>
<Box sx={{ color: `${color}.main`, fontSize: '1.2rem' }}>
{icon}
</Box>
<Box flex={1}>
<Typography variant="subtitle2" color="text.secondary" gutterBottom sx={{ fontWeight: 600, fontSize: '0.85rem' }}>
{title}
</Typography>
<Typography variant="body1" fontWeight={600} color="text.primary" sx={{ fontSize: '0.95rem' }}>
{Array.isArray(value) ? value.join(', ') : value}
</Typography>
</Box>
</Box>
</Paper>
);
title: string,
value: string | string[],
icon: React.ReactNode,
color: 'primary' | 'secondary' | 'success' | 'error' | 'warning' | 'info' = 'primary'
) => <KeyInsightCard title={title} value={value} icon={icon} color={color} />;
/**
* Renders a guidelines card with title, items, and icon

View File

@@ -117,13 +117,28 @@ export const loadExistingAnalysis = async (analysisId: number, website: string):
// Extract domain name for personalization
const extractedDomain = extractDomainName(website);
// Combine all analysis data into a comprehensive object
// Database structure: flat fields at top level
// Need to combine them into the format expected by UI
const comprehensiveAnalysis = {
...result.analysis.style_analysis,
guidelines: result.analysis.style_guidelines,
// Top-level style analysis fields from database
writing_style: result.analysis.writing_style,
content_characteristics: result.analysis.content_characteristics,
target_audience: result.analysis.target_audience,
content_type: result.analysis.content_type,
brand_analysis: result.analysis.brand_analysis,
content_strategy_insights: result.analysis.content_strategy_insights,
recommended_settings: result.analysis.recommended_settings,
// Extract guidelines from style_guidelines object
guidelines: result.analysis.style_guidelines?.guidelines,
best_practices: result.analysis.style_guidelines?.best_practices,
avoid_elements: result.analysis.style_guidelines?.avoid_elements,
content_strategy: result.analysis.style_guidelines?.content_strategy,
ai_generation_tips: result.analysis.style_guidelines?.ai_generation_tips,
competitive_advantages: result.analysis.style_guidelines?.competitive_advantages,
content_calendar_suggestions: result.analysis.style_guidelines?.content_calendar_suggestions,
// Style patterns
style_patterns: result.analysis.style_patterns,
style_consistency: result.analysis.style_patterns?.style_consistency,
unique_elements: result.analysis.style_patterns?.unique_elements
@@ -193,10 +208,13 @@ export const performAnalysis = async (
// Combine all analysis data into a comprehensive object
const comprehensiveAnalysis = {
...result.style_analysis,
guidelines: result.style_guidelines,
guidelines: result.style_guidelines?.guidelines,
best_practices: result.style_guidelines?.best_practices,
avoid_elements: result.style_guidelines?.avoid_elements,
content_strategy: result.style_guidelines?.content_strategy,
ai_generation_tips: result.style_guidelines?.ai_generation_tips,
competitive_advantages: result.style_guidelines?.competitive_advantages,
content_calendar_suggestions: result.style_guidelines?.content_calendar_suggestions,
style_patterns: result.style_patterns,
style_consistency: result.style_patterns?.style_consistency,
unique_elements: result.style_patterns?.unique_elements

View File

@@ -6,8 +6,9 @@ export const useOnboardingStyles = () => {
const styles = {
// Layout styles
container: {
maxWidth: 800,
mx: 'auto',
maxWidth: '100%', // Use full width for maximum data display
mx: 0, // Remove auto margins to use full width
px: { xs: 1, md: 2 }, // Minimal padding to maximize content area
},
// Header styles
@@ -241,17 +242,25 @@ export const useOnboardingStyles = () => {
analysisContainer: {
display: 'flex',
flexDirection: 'column',
gap: 2,
gap: 3,
width: '100%',
maxWidth: '100%', // Use full width for maximum data display
mx: 0, // Remove auto margins to use full width
px: { xs: 1, md: 2 }, // Minimal padding to maximize content area
},
analysisHeaderCard: {
mb: 2,
background: 'linear-gradient(135deg, rgba(255, 255, 255, 0.05) 0%, rgba(255, 255, 255, 0.08) 100%)',
borderRadius: 2,
boxShadow: '0 8px 32px rgba(0, 0, 0, 0.4)',
border: `1px solid rgba(255, 255, 255, 0.1)`,
backdropFilter: 'blur(20px)',
mb: 3,
background: theme.palette.mode === 'dark'
? 'linear-gradient(135deg, rgba(255, 255, 255, 0.05) 0%, rgba(255, 255, 255, 0.08) 100%)'
: 'linear-gradient(135deg, #ffffff 0%, #f8fafc 100%)',
borderRadius: 3,
boxShadow: theme.palette.mode === 'dark'
? '0 8px 32px rgba(0, 0, 0, 0.4)'
: '0 4px 20px rgba(0, 0, 0, 0.08)',
border: theme.palette.mode === 'dark'
? `1px solid rgba(255, 255, 255, 0.1)`
: `1px solid ${alpha(theme.palette.primary.main, 0.1)}`,
overflow: 'hidden',
},
@@ -274,12 +283,12 @@ export const useOnboardingStyles = () => {
analysisHeaderTitle: {
fontWeight: 700,
letterSpacing: '-0.025em',
color: theme.palette.text.primary,
color: theme.palette.mode === 'dark' ? '#ffffff' : '#1a202c', // High contrast dark text
fontSize: '1.5rem',
},
analysisHeaderSubtitle: {
color: theme.palette.text.secondary,
color: theme.palette.mode === 'dark' ? '#e2e8f0' : '#4a5568', // High contrast secondary text
fontSize: '0.95rem',
lineHeight: 1.5,
mt: 0.5,
@@ -292,11 +301,19 @@ export const useOnboardingStyles = () => {
analysisSectionHeader: {
display: 'flex',
alignItems: 'center',
gap: 1,
fontWeight: 600,
color: theme.palette.text.primary,
fontSize: '1.1rem',
mb: 1.5,
gap: 1.5,
fontWeight: 700,
color: theme.palette.mode === 'dark' ? '#ffffff' : '#1a202c', // High contrast dark text
fontSize: '1.25rem',
mb: 2,
pb: 1.5,
borderBottom: `3px solid ${theme.palette.mode === 'dark'
? alpha(theme.palette.primary.main, 0.4)
: alpha(theme.palette.primary.main, 0.25)}`, // More prominent border
'& .MuiSvgIcon-root': {
fontSize: '1.5rem',
color: theme.palette.mode === 'dark' ? theme.palette.primary.light : theme.palette.primary.main,
}
},
analysisSubheader: {