diff --git a/frontend/src/components/common/PageHeader.tsx b/frontend/src/components/common/PageHeader.tsx index e63e5efe..8f6b9f8d 100644 --- a/frontend/src/components/common/PageHeader.tsx +++ b/frontend/src/components/common/PageHeader.tsx @@ -3,6 +3,7 @@ * Used across all Planner and Writer module pages * Includes: Page title, last updated, site/sector info, and selectors */ +import React, { ReactNode } from 'react'; import { useSiteStore } from '../../store/siteStore'; import { useSectorStore } from '../../store/sectorStore'; import SiteAndSectorSelector from './SiteAndSectorSelector'; @@ -13,6 +14,10 @@ interface PageHeaderProps { showRefresh?: boolean; onRefresh?: () => void; className?: string; + badge?: { + icon: ReactNode; + color: 'blue' | 'green' | 'purple' | 'orange' | 'red' | 'indigo'; + }; } export default function PageHeader({ @@ -21,14 +26,33 @@ export default function PageHeader({ showRefresh = false, onRefresh, className = "", + badge, }: PageHeaderProps) { const { activeSite } = useSiteStore(); const { activeSector } = useSectorStore(); + const badgeColors = { + blue: 'bg-blue-600 dark:bg-blue-500', + green: 'bg-green-600 dark:bg-green-500', + purple: 'bg-purple-600 dark:bg-purple-500', + orange: 'bg-orange-600 dark:bg-orange-500', + red: 'bg-red-600 dark:bg-red-500', + indigo: 'bg-indigo-600 dark:bg-indigo-500', + }; + return (
-

{title}

+
+ {badge && ( +
+ {badge.icon && typeof badge.icon === 'object' && 'type' in badge.icon + ? React.cloneElement(badge.icon as React.ReactElement, { className: 'text-white size-5' }) + : badge.icon} +
+ )} +

{title}

+
{lastUpdated && ( <> diff --git a/frontend/src/pages/Planner/Clusters.tsx b/frontend/src/pages/Planner/Clusters.tsx index 6670ed2c..a8a4e66f 100644 --- a/frontend/src/pages/Planner/Clusters.tsx +++ b/frontend/src/pages/Planner/Clusters.tsx @@ -385,11 +385,12 @@ export default function Clusters() { return ( <> - + , color: 'green' }} + /> } - subtitle="Organize keywords into content clusters for better SEO strategy" + hideHeader={true} columns={pageConfig.columns} data={clusters} loading={loading} diff --git a/frontend/src/pages/Planner/Dashboard.tsx b/frontend/src/pages/Planner/Dashboard.tsx index 5f77be50..2d949204 100644 --- a/frontend/src/pages/Planner/Dashboard.tsx +++ b/frontend/src/pages/Planner/Dashboard.tsx @@ -473,6 +473,7 @@ export default function PlannerDashboard() { lastUpdated={lastUpdated} showRefresh={true} onRefresh={fetchDashboardData} + badge={{ icon: , color: 'blue' }} /> {/* Hero Section - Key Metric */} diff --git a/frontend/src/pages/Planner/Ideas.tsx b/frontend/src/pages/Planner/Ideas.tsx index c85813b4..f9ff06a9 100644 --- a/frontend/src/pages/Planner/Ideas.tsx +++ b/frontend/src/pages/Planner/Ideas.tsx @@ -295,11 +295,12 @@ export default function Ideas() { return ( <> - + , color: 'orange' }} + /> } - subtitle="Generate and organize content ideas based on keyword research" + hideHeader={true} columns={pageConfig.columns} data={ideas} loading={loading} diff --git a/frontend/src/pages/Planner/Keywords.tsx b/frontend/src/pages/Planner/Keywords.tsx index 684000be..b243d1b0 100644 --- a/frontend/src/pages/Planner/Keywords.tsx +++ b/frontend/src/pages/Planner/Keywords.tsx @@ -752,11 +752,12 @@ export default function Keywords() { return ( <> - + , color: 'blue' }} + /> } - subtitle="Manage and organize SEO keywords for content planning" + hideHeader={true} columns={pageConfig.columns} data={keywords} loading={loading} diff --git a/frontend/src/pages/Planner/Mapping.tsx b/frontend/src/pages/Planner/Mapping.tsx index 33e62001..2688f859 100644 --- a/frontend/src/pages/Planner/Mapping.tsx +++ b/frontend/src/pages/Planner/Mapping.tsx @@ -1,12 +1,16 @@ import PageMeta from "../../components/common/PageMeta"; import ComponentCard from "../../components/common/ComponentCard"; import PageHeader from "../../components/common/PageHeader"; +import { PieChartIcon } from "../../icons"; export default function Mapping() { return ( <> - + , color: 'indigo' }} + />

diff --git a/frontend/src/pages/Writer/Content.tsx b/frontend/src/pages/Writer/Content.tsx index 896f6e4a..60ddaa6a 100644 --- a/frontend/src/pages/Writer/Content.tsx +++ b/frontend/src/pages/Writer/Content.tsx @@ -181,11 +181,12 @@ export default function Content() { return ( <> - + , color: 'purple' }} + /> } - subtitle="Review AI-generated content and metadata" + hideHeader={true} columns={pageConfig.columns} data={content} loading={loading} diff --git a/frontend/src/pages/Writer/Dashboard.tsx b/frontend/src/pages/Writer/Dashboard.tsx index 613ee699..4fb081a1 100644 --- a/frontend/src/pages/Writer/Dashboard.tsx +++ b/frontend/src/pages/Writer/Dashboard.tsx @@ -552,6 +552,7 @@ export default function WriterDashboard() { lastUpdated={lastUpdated} showRefresh={true} onRefresh={fetchDashboardData} + badge={{ icon: , color: 'green' }} /> {/* Hero Section - Key Metric */} diff --git a/frontend/src/pages/Writer/Images.tsx b/frontend/src/pages/Writer/Images.tsx index 82cacda2..35278a51 100644 --- a/frontend/src/pages/Writer/Images.tsx +++ b/frontend/src/pages/Writer/Images.tsx @@ -385,11 +385,12 @@ export default function Images() { return ( <> - + , color: 'purple' }} + /> } - subtitle="Manage images for content articles" + hideHeader={true} columns={pageConfig.columns} data={images} loading={loading} diff --git a/frontend/src/pages/Writer/Tasks.tsx b/frontend/src/pages/Writer/Tasks.tsx index f8d2fc4a..e7696386 100644 --- a/frontend/src/pages/Writer/Tasks.tsx +++ b/frontend/src/pages/Writer/Tasks.tsx @@ -711,9 +711,7 @@ export default function Tasks() {

} - subtitle="Manage content generation queue and tasks" + hideHeader={true} columns={pageConfig.columns} data={tasks} loading={loading} diff --git a/frontend/src/templates/TablePageTemplate.tsx b/frontend/src/templates/TablePageTemplate.tsx index e2facaaa..aca54da0 100644 --- a/frontend/src/templates/TablePageTemplate.tsx +++ b/frontend/src/templates/TablePageTemplate.tsx @@ -82,9 +82,10 @@ interface HeaderMetrics { } interface TablePageTemplateProps { - title: string; + title?: string; // Optional - hide if PageHeader is used titleIcon?: ReactNode; // Icon component for title (e.g., ListIcon) - subtitle?: string; + subtitle?: string; // Optional - hide if PageHeader is used + hideHeader?: boolean; // Hide the header section when PageHeader is used columns: ColumnConfig[]; data: any[]; loading?: boolean; @@ -504,28 +505,32 @@ export default function TablePageTemplate({ return (
- {/* Page Header - Match Keywords.tsx styling */} -
-
-

- {titleIcon && ( -
- {titleIcon} -
+ {/* Page Header - Match Keywords.tsx styling - Hide if hideHeader is true */} + {!hideHeader && ( +
+
+ {title && ( +

+ {titleIcon && ( +
+ {titleIcon} +
+ )} + {title} +

)} - {title} -

- {subtitle && ( -

- {subtitle} -

- )} + {subtitle && ( +

+ {subtitle} +

+ )} +
+ {/* Sector Selector - Replaces notification card */} +
+ +
- {/* Sector Selector - Replaces notification card */} -
- -
-
+ )} {/* Filters Row - 75% centered, container inside stretched to 100% */} {(renderFilters || filters.length > 0) && (