Section 3: Implement ThreeWidgetFooter on Planner & Writer pages

- Created ThreeWidgetFooter.tsx component with 3-column layout:
  - Widget 1: Page Progress (current page metrics + progress bar + hint)
  - Widget 2: Module Stats (workflow pipeline with links)
  - Widget 3: Completion (both modules summary)
- Created useThreeWidgetFooter.ts hook for building widget props
- Integrated ThreeWidgetFooter into:
  - Planner: Keywords, Clusters, Ideas pages
  - Writer: Tasks, Content pages
- SiteCard already has SiteSetupChecklist integrated (compact mode)
- Backend serializer returns all required fields
This commit is contained in:
IGNY8 VPS (Salman)
2025-12-27 18:01:33 +00:00
parent a145e6742e
commit 627938aa95
5 changed files with 381 additions and 178 deletions

View File

@@ -27,7 +27,7 @@ import { useSectorStore } from '../../store/sectorStore';
import { usePageSizeStore } from '../../store/pageSizeStore';
import { getDifficultyLabelFromNumber, getDifficultyRange } from '../../utils/difficulty';
import PageHeader from '../../components/common/PageHeader';
import ModuleMetricsFooter, { MetricItem, ProgressMetric } from '../../components/dashboard/ModuleMetricsFooter';
import ThreeWidgetFooter from '../../components/dashboard/ThreeWidgetFooter';
export default function Clusters() {
const toast = useToast();
@@ -486,37 +486,81 @@ export default function Clusters() {
}}
/>
{/* Module Metrics Footer - Pipeline Style with Cross-Module Links */}
<ModuleMetricsFooter
metrics={[
{
title: 'Keywords',
value: clusters.reduce((sum, c) => sum + (c.keywords_count || 0), 0).toLocaleString(),
subtitle: `in ${totalCount} clusters`,
icon: <ListIcon className="w-5 h-5" />,
accentColor: 'blue',
href: '/planner/keywords',
{/* Three Widget Footer - Section 3 Layout */}
<ThreeWidgetFooter
submoduleColor="green"
pageProgress={{
title: 'Page Progress',
submoduleColor: 'green',
metrics: [
{ label: 'Clusters', value: totalCount },
{ label: 'With Ideas', value: clusters.filter(c => (c.ideas_count || 0) > 0).length, percentage: `${totalCount > 0 ? Math.round((clusters.filter(c => (c.ideas_count || 0) > 0).length / totalCount) * 100) : 0}%` },
{ label: 'Keywords', value: clusters.reduce((sum, c) => sum + (c.keywords_count || 0), 0) },
{ label: 'Ready', value: clusters.filter(c => (c.ideas_count || 0) === 0).length },
],
progress: {
value: totalCount > 0 ? Math.round((clusters.filter(c => (c.ideas_count || 0) > 0).length / totalCount) * 100) : 0,
label: 'Have Ideas',
color: 'green',
},
{
title: 'Content Ideas',
value: clusters.reduce((sum, c) => sum + (c.ideas_count || 0), 0).toLocaleString(),
subtitle: `across ${clusters.filter(c => (c.ideas_count || 0) > 0).length} clusters`,
icon: <BoltIcon className="w-5 h-5" />,
accentColor: 'green',
href: '/planner/ideas',
},
{
title: 'Ready to Write',
value: clusters.filter(c => (c.ideas_count || 0) > 0 && c.status === 'active').length.toLocaleString(),
subtitle: 'clusters with approved ideas',
icon: <GroupIcon className="w-5 h-5" />,
accentColor: 'purple',
},
]}
progress={{
label: 'Idea Generation Pipeline: Clusters with content ideas generated (ready for downstream content creation)',
value: totalCount > 0 ? Math.round((clusters.filter(c => (c.ideas_count || 0) > 0).length / totalCount) * 100) : 0,
color: 'purple',
hint: clusters.filter(c => (c.ideas_count || 0) === 0).length > 0
? `${clusters.filter(c => (c.ideas_count || 0) === 0).length} clusters ready for idea generation`
: 'All clusters have ideas!',
}}
moduleStats={{
title: 'Planner Module',
pipeline: [
{
fromLabel: 'Keywords',
fromValue: clusters.reduce((sum, c) => sum + (c.keywords_count || 0), 0),
fromHref: '/planner/keywords',
actionLabel: 'Auto Cluster',
toLabel: 'Clusters',
toValue: totalCount,
progress: 100,
color: 'blue',
},
{
fromLabel: 'Clusters',
fromValue: totalCount,
actionLabel: 'Generate Ideas',
toLabel: 'Ideas',
toValue: clusters.reduce((sum, c) => sum + (c.ideas_count || 0), 0),
toHref: '/planner/ideas',
progress: totalCount > 0 ? Math.round((clusters.filter(c => (c.ideas_count || 0) > 0).length / totalCount) * 100) : 0,
color: 'green',
},
{
fromLabel: 'Ideas',
fromValue: clusters.reduce((sum, c) => sum + (c.ideas_count || 0), 0),
fromHref: '/planner/ideas',
actionLabel: 'Create Tasks',
toLabel: 'Tasks',
toValue: 0,
toHref: '/writer/tasks',
progress: 0,
color: 'amber',
},
],
links: [
{ label: 'Keywords', href: '/planner/keywords' },
{ label: 'Clusters', href: '/planner/clusters' },
{ label: 'Ideas', href: '/planner/ideas' },
],
}}
completion={{
title: 'Workflow Completion',
plannerItems: [
{ label: 'Keywords Clustered', value: clusters.reduce((sum, c) => sum + (c.keywords_count || 0), 0), color: 'blue' },
{ label: 'Clusters Created', value: totalCount, color: 'green' },
{ label: 'Ideas Generated', value: clusters.reduce((sum, c) => sum + (c.ideas_count || 0), 0), color: 'amber' },
],
writerItems: [
{ label: 'Content Generated', value: 0, color: 'blue' },
{ label: 'Images Created', value: 0, color: 'purple' },
{ label: 'Published', value: 0, color: 'green' },
],
analyticsHref: '/account/usage',
}}
/>