udpdates
This commit is contained in:
@@ -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 (
|
||||
<div className={`flex flex-col sm:flex-row items-start sm:items-center justify-between gap-4 ${className}`}>
|
||||
<div className="flex-1">
|
||||
<div className="flex items-center gap-3">
|
||||
{badge && (
|
||||
<div className={`flex items-center justify-center w-10 h-10 rounded-xl ${badgeColors[badge.color]} flex-shrink-0`}>
|
||||
{badge.icon && typeof badge.icon === 'object' && 'type' in badge.icon
|
||||
? React.cloneElement(badge.icon as React.ReactElement, { className: 'text-white size-5' })
|
||||
: badge.icon}
|
||||
</div>
|
||||
)}
|
||||
<h2 className="text-2xl font-bold text-gray-800 dark:text-white/90">{title}</h2>
|
||||
</div>
|
||||
<div className="flex items-center gap-3 mt-1">
|
||||
{lastUpdated && (
|
||||
<>
|
||||
|
||||
@@ -385,11 +385,12 @@ export default function Clusters() {
|
||||
|
||||
return (
|
||||
<>
|
||||
<PageHeader title="Keyword Clusters" />
|
||||
<TablePageTemplate
|
||||
<PageHeader
|
||||
title="Keyword Clusters"
|
||||
titleIcon={<GroupIcon className="text-success-500 size-5" />}
|
||||
subtitle="Organize keywords into content clusters for better SEO strategy"
|
||||
badge={{ icon: <GroupIcon />, color: 'green' }}
|
||||
/>
|
||||
<TablePageTemplate
|
||||
hideHeader={true}
|
||||
columns={pageConfig.columns}
|
||||
data={clusters}
|
||||
loading={loading}
|
||||
|
||||
@@ -473,6 +473,7 @@ export default function PlannerDashboard() {
|
||||
lastUpdated={lastUpdated}
|
||||
showRefresh={true}
|
||||
onRefresh={fetchDashboardData}
|
||||
badge={{ icon: <PieChartIcon />, color: 'blue' }}
|
||||
/>
|
||||
|
||||
{/* Hero Section - Key Metric */}
|
||||
|
||||
@@ -295,11 +295,12 @@ export default function Ideas() {
|
||||
|
||||
return (
|
||||
<>
|
||||
<PageHeader title="Content Ideas" />
|
||||
<TablePageTemplate
|
||||
<PageHeader
|
||||
title="Content Ideas"
|
||||
titleIcon={<BoltIcon className="text-warning-500 size-5" />}
|
||||
subtitle="Generate and organize content ideas based on keyword research"
|
||||
badge={{ icon: <BoltIcon />, color: 'orange' }}
|
||||
/>
|
||||
<TablePageTemplate
|
||||
hideHeader={true}
|
||||
columns={pageConfig.columns}
|
||||
data={ideas}
|
||||
loading={loading}
|
||||
|
||||
@@ -752,11 +752,12 @@ export default function Keywords() {
|
||||
|
||||
return (
|
||||
<>
|
||||
<PageHeader title="Keywords" />
|
||||
<TablePageTemplate
|
||||
<PageHeader
|
||||
title="Keywords"
|
||||
titleIcon={<ListIcon className="text-brand-500 size-5" />}
|
||||
subtitle="Manage and organize SEO keywords for content planning"
|
||||
badge={{ icon: <ListIcon />, color: 'blue' }}
|
||||
/>
|
||||
<TablePageTemplate
|
||||
hideHeader={true}
|
||||
columns={pageConfig.columns}
|
||||
data={keywords}
|
||||
loading={loading}
|
||||
|
||||
@@ -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 (
|
||||
<>
|
||||
<PageMeta title="Content Mapping - IGNY8" description="Keyword to content mapping" />
|
||||
<PageHeader title="Content Mapping" />
|
||||
<PageHeader
|
||||
title="Content Mapping"
|
||||
badge={{ icon: <PieChartIcon />, color: 'indigo' }}
|
||||
/>
|
||||
<ComponentCard title="Coming Soon" desc="Keyword to content mapping">
|
||||
<div className="text-center py-8">
|
||||
<p className="text-gray-600 dark:text-gray-400">
|
||||
|
||||
@@ -181,11 +181,12 @@ export default function Content() {
|
||||
|
||||
return (
|
||||
<>
|
||||
<PageHeader title="Content" />
|
||||
<TablePageTemplate
|
||||
<PageHeader
|
||||
title="Content"
|
||||
titleIcon={<FileIcon className="text-brand-500 size-5" />}
|
||||
subtitle="Review AI-generated content and metadata"
|
||||
badge={{ icon: <FileIcon />, color: 'purple' }}
|
||||
/>
|
||||
<TablePageTemplate
|
||||
hideHeader={true}
|
||||
columns={pageConfig.columns}
|
||||
data={content}
|
||||
loading={loading}
|
||||
|
||||
@@ -552,6 +552,7 @@ export default function WriterDashboard() {
|
||||
lastUpdated={lastUpdated}
|
||||
showRefresh={true}
|
||||
onRefresh={fetchDashboardData}
|
||||
badge={{ icon: <PencilIcon />, color: 'green' }}
|
||||
/>
|
||||
|
||||
{/* Hero Section - Key Metric */}
|
||||
|
||||
@@ -385,11 +385,12 @@ export default function Images() {
|
||||
|
||||
return (
|
||||
<>
|
||||
<PageHeader title="Content Images" />
|
||||
<TablePageTemplate
|
||||
<PageHeader
|
||||
title="Content Images"
|
||||
titleIcon={<FileIcon className="text-purple-500 size-5" />}
|
||||
subtitle="Manage images for content articles"
|
||||
badge={{ icon: <FileIcon />, color: 'purple' }}
|
||||
/>
|
||||
<TablePageTemplate
|
||||
hideHeader={true}
|
||||
columns={pageConfig.columns}
|
||||
data={images}
|
||||
loading={loading}
|
||||
|
||||
@@ -711,9 +711,7 @@ export default function Tasks() {
|
||||
<ViewToggle currentView={currentView} onViewChange={setCurrentView} />
|
||||
</div>
|
||||
<TablePageTemplate
|
||||
title="Tasks"
|
||||
titleIcon={<TaskIcon className="text-brand-500 size-5" />}
|
||||
subtitle="Manage content generation queue and tasks"
|
||||
hideHeader={true}
|
||||
columns={pageConfig.columns}
|
||||
data={tasks}
|
||||
loading={loading}
|
||||
|
||||
@@ -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,9 +505,11 @@ export default function TablePageTemplate({
|
||||
|
||||
return (
|
||||
<div className={className}>
|
||||
{/* Page Header - Match Keywords.tsx styling */}
|
||||
{/* Page Header - Match Keywords.tsx styling - Hide if hideHeader is true */}
|
||||
{!hideHeader && (
|
||||
<div className="flex justify-between items-center mb-6 overflow-visible">
|
||||
<div className="flex-1 min-w-0">
|
||||
{title && (
|
||||
<h2 className="text-xl font-semibold text-gray-800 dark:text-white/90 flex items-center gap-2">
|
||||
{titleIcon && (
|
||||
<div className="flex items-center justify-center w-10 h-10 bg-blue-50 rounded-xl dark:bg-blue-500/10">
|
||||
@@ -515,6 +518,7 @@ export default function TablePageTemplate({
|
||||
)}
|
||||
{title}
|
||||
</h2>
|
||||
)}
|
||||
{subtitle && (
|
||||
<p className="mt-1 text-sm text-gray-500 dark:text-gray-400">
|
||||
{subtitle}
|
||||
@@ -526,6 +530,7 @@ export default function TablePageTemplate({
|
||||
<SectorSelector />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Filters Row - 75% centered, container inside stretched to 100% */}
|
||||
{(renderFilters || filters.length > 0) && (
|
||||
|
||||
Reference in New Issue
Block a user