Added onboarding progress tracking & landing page
This commit is contained in:
@@ -0,0 +1,507 @@
|
||||
/**
|
||||
* Website Step Rendering Utility Functions
|
||||
* Extracted rendering components for website analysis display
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import {
|
||||
Box,
|
||||
Typography,
|
||||
Paper,
|
||||
Card,
|
||||
CardContent,
|
||||
Grid,
|
||||
Accordion,
|
||||
AccordionSummary,
|
||||
AccordionDetails,
|
||||
Alert,
|
||||
Button,
|
||||
Slide,
|
||||
Zoom,
|
||||
Divider
|
||||
} from '@mui/material';
|
||||
import {
|
||||
ExpandMore as ExpandMoreIcon,
|
||||
CheckCircle as CheckIcon,
|
||||
Info as InfoIcon,
|
||||
Psychology as PsychologyIcon,
|
||||
TrendingUp as TrendingUpIcon,
|
||||
Analytics as AnalyticsIcon,
|
||||
Business as BusinessIcon,
|
||||
AutoAwesome as AutoAwesomeIcon,
|
||||
Star as StarIcon,
|
||||
Warning as WarningIcon,
|
||||
Language as LanguageIcon,
|
||||
Web as WebIcon,
|
||||
Palette as PaletteIcon,
|
||||
Speed as SpeedIcon,
|
||||
Group as GroupIcon
|
||||
} from '@mui/icons-material';
|
||||
|
||||
/**
|
||||
* Renders a key insight card with icon and value
|
||||
*/
|
||||
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>
|
||||
);
|
||||
|
||||
/**
|
||||
* Renders a guidelines card with title, items, and icon
|
||||
*/
|
||||
export const renderGuidelinesCard = (
|
||||
title: string,
|
||||
items: string[],
|
||||
icon: React.ReactNode,
|
||||
color: string = 'primary'
|
||||
) => (
|
||||
<Zoom in timeout={600}>
|
||||
<Card sx={{ mb: 2, border: `1px solid ${color}.light` }}>
|
||||
<CardContent>
|
||||
<Box display="flex" alignItems="center" gap={1} mb={2}>
|
||||
<Box sx={{ color: `${color}.main` }}>
|
||||
{icon}
|
||||
</Box>
|
||||
<Typography variant="h6" fontWeight={600}>
|
||||
{title}
|
||||
</Typography>
|
||||
</Box>
|
||||
<Box component="ul" sx={{ pl: 2, m: 0 }}>
|
||||
{items.map((item, index) => (
|
||||
<Typography component="li" variant="body2" key={index} sx={{ mb: 1, lineHeight: 1.6 }}>
|
||||
{item}
|
||||
</Typography>
|
||||
))}
|
||||
</Box>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Zoom>
|
||||
);
|
||||
|
||||
/**
|
||||
* Renders the pro upgrade alert
|
||||
*/
|
||||
export const renderProUpgradeAlert = () => (
|
||||
<Slide direction="up" in timeout={1000}>
|
||||
<Alert
|
||||
severity="info"
|
||||
sx={{
|
||||
mb: 3,
|
||||
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
|
||||
color: 'white',
|
||||
'& .MuiAlert-icon': { color: 'white' }
|
||||
}}
|
||||
action={
|
||||
<Button color="inherit" size="small" variant="outlined" sx={{ color: 'white', borderColor: 'white' }}>
|
||||
Learn More
|
||||
</Button>
|
||||
}
|
||||
>
|
||||
<Typography variant="subtitle2" gutterBottom>
|
||||
<StarIcon sx={{ mr: 1, verticalAlign: 'middle' }} />
|
||||
Limited Analysis Scope
|
||||
</Typography>
|
||||
<Typography variant="body2">
|
||||
This analysis is based on your homepage only. <strong>ALwrity Pro</strong> can index your entire website and social media content for comprehensive personalized content generation.
|
||||
</Typography>
|
||||
</Alert>
|
||||
</Slide>
|
||||
);
|
||||
|
||||
/**
|
||||
* Renders the brand analysis section
|
||||
*/
|
||||
export const renderBrandAnalysisSection = (brandAnalysis: any) => (
|
||||
<Zoom in timeout={700}>
|
||||
<Card sx={{ mb: 2, border: '2px solid info.light', background: 'info.50' }}>
|
||||
<CardContent>
|
||||
<Box display="flex" alignItems="center" gap={1} mb={2}>
|
||||
<BusinessIcon color="info" />
|
||||
<Typography variant="h6" fontWeight={600} color="info.main">
|
||||
Brand Analysis
|
||||
</Typography>
|
||||
</Box>
|
||||
|
||||
<Grid container spacing={2}>
|
||||
{brandAnalysis.brand_voice && (
|
||||
<Grid item xs={12} md={6}>
|
||||
<Typography variant="subtitle2" color="primary" gutterBottom>
|
||||
Brand Voice:
|
||||
</Typography>
|
||||
<Typography variant="body2" sx={{ mb: 2 }}>
|
||||
{brandAnalysis.brand_voice}
|
||||
</Typography>
|
||||
</Grid>
|
||||
)}
|
||||
|
||||
{brandAnalysis.brand_positioning && (
|
||||
<Grid item xs={12} md={6}>
|
||||
<Typography variant="subtitle2" color="primary" gutterBottom>
|
||||
Brand Positioning:
|
||||
</Typography>
|
||||
<Typography variant="body2" sx={{ mb: 2 }}>
|
||||
{brandAnalysis.brand_positioning}
|
||||
</Typography>
|
||||
</Grid>
|
||||
)}
|
||||
|
||||
{brandAnalysis.brand_values && brandAnalysis.brand_values.length > 0 && (
|
||||
<Grid item xs={12}>
|
||||
<Typography variant="subtitle2" color="primary" gutterBottom>
|
||||
Brand Values:
|
||||
</Typography>
|
||||
<Box component="ul" sx={{ pl: 2, m: 0 }}>
|
||||
{brandAnalysis.brand_values.map((value: string, index: number) => (
|
||||
<Typography component="li" variant="body2" key={index} sx={{ mb: 1 }}>
|
||||
{value}
|
||||
</Typography>
|
||||
))}
|
||||
</Box>
|
||||
</Grid>
|
||||
)}
|
||||
</Grid>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Zoom>
|
||||
);
|
||||
|
||||
/**
|
||||
* Renders the content strategy insights section
|
||||
*/
|
||||
export const renderContentStrategyInsightsSection = (insights: any) => (
|
||||
<Zoom in timeout={800}>
|
||||
<Card sx={{ mb: 2, border: '2px solid secondary.light', background: 'secondary.50' }}>
|
||||
<CardContent>
|
||||
<Box display="flex" alignItems="center" gap={1} mb={2}>
|
||||
<AnalyticsIcon color="secondary" />
|
||||
<Typography variant="h6" fontWeight={600} color="secondary.main">
|
||||
Content Strategy Insights
|
||||
</Typography>
|
||||
</Box>
|
||||
|
||||
<Grid container spacing={3}>
|
||||
{insights.strengths && insights.strengths.length > 0 && (
|
||||
<Grid item xs={12} md={6}>
|
||||
<Typography variant="subtitle2" color="success.main" gutterBottom>
|
||||
✅ Strengths:
|
||||
</Typography>
|
||||
<Box component="ul" sx={{ pl: 2, m: 0 }}>
|
||||
{insights.strengths.map((strength: string, index: number) => (
|
||||
<Typography component="li" variant="body2" key={index} sx={{ mb: 1 }}>
|
||||
{strength}
|
||||
</Typography>
|
||||
))}
|
||||
</Box>
|
||||
</Grid>
|
||||
)}
|
||||
|
||||
{insights.opportunities && insights.opportunities.length > 0 && (
|
||||
<Grid item xs={12} md={6}>
|
||||
<Typography variant="subtitle2" color="info.main" gutterBottom>
|
||||
🎯 Opportunities:
|
||||
</Typography>
|
||||
<Box component="ul" sx={{ pl: 2, m: 0 }}>
|
||||
{insights.opportunities.map((opportunity: string, index: number) => (
|
||||
<Typography component="li" variant="body2" key={index} sx={{ mb: 1 }}>
|
||||
{opportunity}
|
||||
</Typography>
|
||||
))}
|
||||
</Box>
|
||||
</Grid>
|
||||
)}
|
||||
|
||||
{insights.recommended_improvements && insights.recommended_improvements.length > 0 && (
|
||||
<Grid item xs={12}>
|
||||
<Typography variant="subtitle2" color="primary" gutterBottom>
|
||||
🔧 Recommended Improvements:
|
||||
</Typography>
|
||||
<Box component="ul" sx={{ pl: 2, m: 0 }}>
|
||||
{insights.recommended_improvements.map((improvement: string, index: number) => (
|
||||
<Typography component="li" variant="body2" key={index} sx={{ mb: 1 }}>
|
||||
{improvement}
|
||||
</Typography>
|
||||
))}
|
||||
</Box>
|
||||
</Grid>
|
||||
)}
|
||||
</Grid>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Zoom>
|
||||
);
|
||||
|
||||
/**
|
||||
* Renders the AI generation tips section
|
||||
*/
|
||||
export const renderAIGenerationTipsSection = (tips: string[]) => (
|
||||
<Zoom in timeout={900}>
|
||||
<Card sx={{ mb: 2, border: '2px solid primary.light', background: 'primary.50' }}>
|
||||
<CardContent>
|
||||
<Box display="flex" alignItems="center" gap={1} mb={2}>
|
||||
<AutoAwesomeIcon color="primary" />
|
||||
<Typography variant="h6" fontWeight={600} color="primary.main">
|
||||
AI Content Generation Tips
|
||||
</Typography>
|
||||
</Box>
|
||||
<Box component="ul" sx={{ pl: 2, m: 0 }}>
|
||||
{tips.map((tip: string, index: number) => (
|
||||
<Typography component="li" variant="body2" key={index} sx={{ mb: 1, lineHeight: 1.6 }}>
|
||||
{tip}
|
||||
</Typography>
|
||||
))}
|
||||
</Box>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Zoom>
|
||||
);
|
||||
|
||||
/**
|
||||
* Renders a best practices section card
|
||||
*/
|
||||
export const renderBestPracticesSection = (bestPractices: string[]) => (
|
||||
<Zoom in timeout={800}>
|
||||
<Card sx={{ border: '2px solid success.light', background: 'success.50' }}>
|
||||
<CardContent>
|
||||
<Box display="flex" alignItems="center" gap={1} mb={2}>
|
||||
<CheckIcon color="success" />
|
||||
<Typography variant="h6" fontWeight={600} color="success.main">
|
||||
Best Practices
|
||||
</Typography>
|
||||
</Box>
|
||||
<Box component="ul" sx={{ pl: 2, m: 0 }}>
|
||||
{bestPractices.map((practice, index) => (
|
||||
<Typography component="li" variant="body2" key={index} sx={{ mb: 1, lineHeight: 1.6 }}>
|
||||
{practice}
|
||||
</Typography>
|
||||
))}
|
||||
</Box>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Zoom>
|
||||
);
|
||||
|
||||
/**
|
||||
* Renders an avoid elements section card
|
||||
*/
|
||||
export const renderAvoidElementsSection = (avoidElements: string[]) => (
|
||||
<Zoom in timeout={1000}>
|
||||
<Card sx={{ border: '2px solid warning.light', background: 'warning.50' }}>
|
||||
<CardContent>
|
||||
<Box display="flex" alignItems="center" gap={1} mb={2}>
|
||||
<WarningIcon color="warning" />
|
||||
<Typography variant="h6" fontWeight={600} color="warning.main">
|
||||
Elements to Avoid
|
||||
</Typography>
|
||||
</Box>
|
||||
<Box component="ul" sx={{ pl: 2, m: 0 }}>
|
||||
{avoidElements.map((element, index) => (
|
||||
<Typography component="li" variant="body2" key={index} sx={{ mb: 1, lineHeight: 1.6 }}>
|
||||
{element}
|
||||
</Typography>
|
||||
))}
|
||||
</Box>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Zoom>
|
||||
);
|
||||
|
||||
/**
|
||||
* Renders a generic analysis section accordion
|
||||
*/
|
||||
export const renderAnalysisSection = (
|
||||
title: string,
|
||||
data: any,
|
||||
icon: React.ReactNode,
|
||||
description?: string
|
||||
) => (
|
||||
<Accordion key={title} sx={{ mb: 2 }}>
|
||||
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
|
||||
<Box display="flex" alignItems="center" gap={1}>
|
||||
{icon}
|
||||
<Typography variant="h6">{title}</Typography>
|
||||
</Box>
|
||||
</AccordionSummary>
|
||||
<AccordionDetails>
|
||||
{description && (
|
||||
<Typography variant="body2" color="textSecondary" sx={{ mb: 2 }}>
|
||||
{description}
|
||||
</Typography>
|
||||
)}
|
||||
<Grid container spacing={2}>
|
||||
{Object.entries(data).map(([key, value]) => (
|
||||
<Grid item xs={12} md={6} key={key}>
|
||||
<Typography variant="subtitle2" color="primary" gutterBottom>
|
||||
{key.replace(/_/g, ' ').replace(/\b\w/g, l => l.toUpperCase())}:
|
||||
</Typography>
|
||||
<Typography variant="body2">
|
||||
{Array.isArray(value) ? value.join(', ') : String(value)}
|
||||
</Typography>
|
||||
</Grid>
|
||||
))}
|
||||
</Grid>
|
||||
</AccordionDetails>
|
||||
</Accordion>
|
||||
);
|
||||
|
||||
/**
|
||||
* Renders the guidelines section accordion
|
||||
*/
|
||||
export const renderGuidelinesSection = (guidelines: any) => (
|
||||
<Accordion sx={{ mb: 2 }}>
|
||||
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
|
||||
<Box display="flex" alignItems="center" gap={1}>
|
||||
<PsychologyIcon color="primary" />
|
||||
<Typography variant="h6">Content Guidelines</Typography>
|
||||
</Box>
|
||||
</AccordionSummary>
|
||||
<AccordionDetails>
|
||||
<Typography variant="body2" color="textSecondary" sx={{ mb: 2 }}>
|
||||
Personalized recommendations for improving your content creation based on your writing style analysis.
|
||||
</Typography>
|
||||
|
||||
{guidelines.tone_recommendations && (
|
||||
<Box sx={{ mb: 3 }}>
|
||||
<Typography variant="subtitle1" color="primary" gutterBottom>
|
||||
Tone Recommendations
|
||||
</Typography>
|
||||
<Box component="ul" sx={{ pl: 2 }}>
|
||||
{guidelines.tone_recommendations.map((rec: string, index: number) => (
|
||||
<Typography component="li" variant="body2" key={index} sx={{ mb: 1 }}>
|
||||
{rec}
|
||||
</Typography>
|
||||
))}
|
||||
</Box>
|
||||
</Box>
|
||||
)}
|
||||
|
||||
{guidelines.structure_guidelines && (
|
||||
<Box sx={{ mb: 3 }}>
|
||||
<Typography variant="subtitle1" color="primary" gutterBottom>
|
||||
Structure Guidelines
|
||||
</Typography>
|
||||
<Box component="ul" sx={{ pl: 2 }}>
|
||||
{guidelines.structure_guidelines.map((guideline: string, index: number) => (
|
||||
<Typography component="li" variant="body2" key={index} sx={{ mb: 1 }}>
|
||||
{guideline}
|
||||
</Typography>
|
||||
))}
|
||||
</Box>
|
||||
</Box>
|
||||
)}
|
||||
|
||||
{guidelines.vocabulary_suggestions && (
|
||||
<Box sx={{ mb: 3 }}>
|
||||
<Typography variant="subtitle1" color="primary" gutterBottom>
|
||||
Vocabulary Suggestions
|
||||
</Typography>
|
||||
<Box component="ul" sx={{ pl: 2 }}>
|
||||
{guidelines.vocabulary_suggestions.map((suggestion: string, index: number) => (
|
||||
<Typography component="li" variant="body2" key={index} sx={{ mb: 1 }}>
|
||||
{suggestion}
|
||||
</Typography>
|
||||
))}
|
||||
</Box>
|
||||
</Box>
|
||||
)}
|
||||
|
||||
{guidelines.engagement_tips && (
|
||||
<Box sx={{ mb: 3 }}>
|
||||
<Typography variant="subtitle1" color="primary" gutterBottom>
|
||||
Engagement Tips
|
||||
</Typography>
|
||||
<Box component="ul" sx={{ pl: 2 }}>
|
||||
{guidelines.engagement_tips.map((tip: string, index: number) => (
|
||||
<Typography component="li" variant="body2" key={index} sx={{ mb: 1 }}>
|
||||
{tip}
|
||||
</Typography>
|
||||
))}
|
||||
</Box>
|
||||
</Box>
|
||||
)}
|
||||
|
||||
{guidelines.audience_considerations && (
|
||||
<Box sx={{ mb: 3 }}>
|
||||
<Typography variant="subtitle1" color="primary" gutterBottom>
|
||||
Audience Considerations
|
||||
</Typography>
|
||||
<Box component="ul" sx={{ pl: 2 }}>
|
||||
{guidelines.audience_considerations.map((consideration: string, index: number) => (
|
||||
<Typography component="li" variant="body2" key={index} sx={{ mb: 1 }}>
|
||||
{consideration}
|
||||
</Typography>
|
||||
))}
|
||||
</Box>
|
||||
</Box>
|
||||
)}
|
||||
</AccordionDetails>
|
||||
</Accordion>
|
||||
);
|
||||
|
||||
/**
|
||||
* Renders the style patterns section accordion
|
||||
*/
|
||||
export const renderStylePatternsSection = (patterns: any) => (
|
||||
<Accordion sx={{ mb: 2 }}>
|
||||
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
|
||||
<Box display="flex" alignItems="center" gap={1}>
|
||||
<AnalyticsIcon color="secondary" />
|
||||
<Typography variant="h6">Style Patterns</Typography>
|
||||
</Box>
|
||||
</AccordionSummary>
|
||||
<AccordionDetails>
|
||||
<Typography variant="body2" color="textSecondary" sx={{ mb: 2 }}>
|
||||
Recurring patterns and characteristics identified in your writing style.
|
||||
</Typography>
|
||||
|
||||
<Grid container spacing={2}>
|
||||
{Object.entries(patterns).map(([key, value]) => (
|
||||
<Grid item xs={12} md={6} key={key}>
|
||||
<Typography variant="subtitle2" color="primary" gutterBottom>
|
||||
{key.replace(/_/g, ' ').replace(/\b\w/g, l => l.toUpperCase())}:
|
||||
</Typography>
|
||||
<Typography variant="body2">
|
||||
{Array.isArray(value) ? value.join(', ') : String(value)}
|
||||
</Typography>
|
||||
</Grid>
|
||||
))}
|
||||
</Grid>
|
||||
</AccordionDetails>
|
||||
</Accordion>
|
||||
);
|
||||
Reference in New Issue
Block a user