page adn app header mods

This commit is contained in:
IGNY8 VPS (Salman)
2025-12-27 04:09:05 +00:00
parent e5959c3e72
commit fd6e7eb2dd
14 changed files with 494 additions and 547 deletions

View File

@@ -14,7 +14,7 @@ import {
bulkDeleteContent,
} from '../../services/api';
import { optimizerApi } from '../../api/optimizer.api';
import { useNavigate } from 'react-router-dom';
import { useNavigate, Link } from 'react-router-dom';
import { useToast } from '../../components/ui/toast/ToastContainer';
import { FileIcon, TaskIcon, CheckCircleIcon } from '../../icons';
import { createContentPageConfig } from '../../config/pages/content.config';
@@ -24,7 +24,7 @@ import ProgressModal from '../../components/common/ProgressModal';
import { useProgressModal } from '../../hooks/useProgressModal';
import PageHeader from '../../components/common/PageHeader';
import ModuleMetricsFooter, { MetricItem, ProgressMetric } from '../../components/dashboard/ModuleMetricsFooter';
import { WorkflowInsight } from '../../components/common/WorkflowInsights';
import { PencilSquareIcon } from '@heroicons/react/24/outline';
export default function Content() {
const toast = useToast();
@@ -55,59 +55,6 @@ export default function Content() {
const progressModal = useProgressModal();
const hasReloadedRef = useRef(false);
// Calculate workflow insights
const workflowInsights: WorkflowInsight[] = useMemo(() => {
const insights: WorkflowInsight[] = [];
const draftCount = content.filter(c => c.status === 'draft').length;
const reviewCount = content.filter(c => c.status === 'review').length;
const publishedCount = content.filter(c => c.status === 'published').length;
const publishingRate = totalCount > 0 ? Math.round((publishedCount / totalCount) * 100) : 0;
if (totalCount === 0) {
insights.push({
type: 'info',
message: 'No content yet - Generate content from tasks to build your content library',
});
return insights;
}
// Draft vs Review status
if (draftCount > reviewCount * 3 && draftCount >= 5) {
insights.push({
type: 'warning',
message: `${draftCount} drafts waiting for review - Move content to review stage for quality assurance`,
});
} else if (draftCount > 0) {
insights.push({
type: 'info',
message: `${draftCount} drafts in progress - Review and refine before moving to publish stage`,
});
}
// Review queue status
if (reviewCount > 0) {
insights.push({
type: 'action',
message: `${reviewCount} pieces awaiting final review - Approve and publish when ready`,
});
}
// Publishing readiness
if (publishingRate >= 60 && publishedCount >= 10) {
insights.push({
type: 'success',
message: `Strong publishing rate (${publishingRate}%) - ${publishedCount} articles ready for WordPress sync`,
});
} else if (publishedCount > 0) {
insights.push({
type: 'success',
message: `${publishedCount} articles published (${publishingRate}%) - Continue moving content through the pipeline`,
});
}
return insights;
}, [content, totalCount]);
// Load content - wrapped in useCallback
const loadContent = useCallback(async () => {
setLoading(true);
@@ -281,10 +228,20 @@ export default function Content() {
<>
<PageHeader
title="Drafts"
description="AI-generated content ready for review. Add images, edit, and publish when ready."
badge={{ icon: <FileIcon />, color: 'purple' }}
breadcrumb="Writer / Drafts"
workflowInsights={workflowInsights}
description="Manage content drafts"
badge={{ icon: <PencilSquareIcon />, color: 'orange' }}
breadcrumb="Writer"
actions={
<Link
to="/writer/images"
className="inline-flex items-center gap-2 px-3 py-1.5 text-sm font-medium text-white bg-brand-500 hover:bg-brand-600 rounded-lg transition-colors"
>
Generate Images
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
</svg>
</Link>
}
/>
<TablePageTemplate
columns={pageConfig.columns}

View File

@@ -4,6 +4,7 @@
*/
import { useState, useEffect, useMemo, useCallback, useRef } from 'react';
import { Link } from 'react-router-dom';
import TablePageTemplate from '../../templates/TablePageTemplate';
import {
fetchContentImages,
@@ -19,6 +20,7 @@ import {
} from '../../services/api';
import { useToast } from '../../components/ui/toast/ToastContainer';
import { FileIcon, DownloadIcon } from '../../icons';
import { PhotoIcon } from '@heroicons/react/24/outline';
import { createImagesPageConfig } from '../../config/pages/images.config';
import ImageQueueModal, { ImageQueueItem } from '../../components/common/ImageQueueModal';
import SingleRecordStatusUpdateModal from '../../components/common/SingleRecordStatusUpdateModal';
@@ -450,8 +452,20 @@ export default function Images() {
<>
<PageHeader
title="Images"
badge={{ icon: <FileIcon />, color: 'orange' }}
breadcrumb="Writer / Images"
description="Generate and manage content images"
badge={{ icon: <PhotoIcon />, color: 'pink' }}
breadcrumb="Writer"
actions={
<Link
to="/writer/review"
className="inline-flex items-center gap-2 px-3 py-1.5 text-sm font-medium text-white bg-brand-500 hover:bg-brand-600 rounded-lg transition-colors"
>
Review Content
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
</svg>
</Link>
}
/>
<TablePageTemplate
columns={pageConfig.columns}

View File

@@ -4,6 +4,7 @@
*/
import { useState, useEffect, useMemo, useCallback } from 'react';
import { useNavigate, Link } from 'react-router-dom';
import TablePageTemplate from '../../templates/TablePageTemplate';
import {
fetchContent,
@@ -15,9 +16,9 @@ import {
deleteContent,
bulkDeleteContent,
} from '../../services/api';
import { useNavigate } from 'react-router-dom';
import { useToast } from '../../components/ui/toast/ToastContainer';
import { FileIcon, CheckCircleIcon } from '../../icons';
import { RocketLaunchIcon } from '@heroicons/react/24/outline';
import { createPublishedPageConfig } from '../../config/pages/published.config';
import { useSectorStore } from '../../store/sectorStore';
import { usePageSizeStore } from '../../store/pageSizeStore';
@@ -308,8 +309,20 @@ export default function Published() {
<>
<PageHeader
title="Published"
badge={{ icon: <CheckCircleIcon />, color: 'green' }}
breadcrumb="Writer / Published"
description="Published content and WordPress sync status"
badge={{ icon: <RocketLaunchIcon />, color: 'green' }}
breadcrumb="Writer"
actions={
<Link
to="/planner/keywords"
className="inline-flex items-center gap-2 px-3 py-1.5 text-sm font-medium text-white bg-brand-500 hover:bg-brand-600 rounded-lg transition-colors"
>
Create More Content
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
</svg>
</Link>
}
/>
<TablePageTemplate
columns={pageConfig.columns}

View File

@@ -4,6 +4,7 @@
*/
import { useState, useEffect, useMemo, useCallback } from 'react';
import { useNavigate, Link } from 'react-router-dom';
import TablePageTemplate from '../../templates/TablePageTemplate';
import {
fetchContent,
@@ -12,9 +13,9 @@ import {
ContentFilters,
fetchAPI,
} from '../../services/api';
import { useNavigate } from 'react-router-dom';
import { useToast } from '../../components/ui/toast/ToastContainer';
import { CheckCircleIcon } from '../../icons';
import { ClipboardDocumentCheckIcon } from '@heroicons/react/24/outline';
import { createReviewPageConfig } from '../../config/pages/review.config';
import { useSectorStore } from '../../store/sectorStore';
import { usePageSizeStore } from '../../store/pageSizeStore';
@@ -346,9 +347,21 @@ export default function Review() {
return (
<>
<PageHeader
title="Review Queue"
badge={{ icon: <CheckCircleIcon />, color: 'blue' }}
breadcrumb="Writer / Review"
title="Review"
description="Review and approve content before publishing"
badge={{ icon: <ClipboardDocumentCheckIcon />, color: 'emerald' }}
breadcrumb="Writer"
actions={
<Link
to="/writer/published"
className="inline-flex items-center gap-2 px-3 py-1.5 text-sm font-medium text-white bg-brand-500 hover:bg-brand-600 rounded-lg transition-colors"
>
View Published
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
</svg>
</Link>
}
/>
<TablePageTemplate
columns={pageConfig.columns}

View File

@@ -3,7 +3,8 @@
* Consistent with Keywords page layout, structure and design
*/
import { useState, useEffect, useMemo, useCallback, useRef } from 'react';
import { useState, useEffect, useCallback, useRef } from 'react';
import { Link } from 'react-router-dom';
import TablePageTemplate from '../../templates/TablePageTemplate';
import {
fetchTasks,
@@ -30,7 +31,7 @@ import { useSectorStore } from '../../store/sectorStore';
import { usePageSizeStore } from '../../store/pageSizeStore';
import PageHeader from '../../components/common/PageHeader';
import ModuleMetricsFooter, { MetricItem, ProgressMetric } from '../../components/dashboard/ModuleMetricsFooter';
import { WorkflowInsight } from '../../components/common/WorkflowInsights';
import { DocumentTextIcon } from '@heroicons/react/24/outline';
export default function Tasks() {
const toast = useToast();
@@ -79,63 +80,6 @@ export default function Tasks() {
// Progress modal for AI functions
const progressModal = useProgressModal();
// Calculate workflow insights
const workflowInsights: WorkflowInsight[] = useMemo(() => {
const insights: WorkflowInsight[] = [];
const queuedCount = tasks.filter(t => t.status === 'queued').length;
const processingCount = tasks.filter(t => t.status === 'in_progress').length;
const completedCount = tasks.filter(t => t.status === 'completed').length;
const failedCount = tasks.filter(t => t.status === 'failed').length;
const completionRate = totalCount > 0 ? Math.round((completedCount / totalCount) * 100) : 0;
if (totalCount === 0) {
insights.push({
type: 'info',
message: 'No tasks yet - Queue ideas from Planner to start generating content automatically',
});
return insights;
}
// Queue status
if (queuedCount > 10) {
insights.push({
type: 'warning',
message: `Large queue detected (${queuedCount} tasks) - Content generation may take time, consider prioritizing`,
});
} else if (queuedCount > 0) {
insights.push({
type: 'info',
message: `${queuedCount} tasks in queue - Content generation pipeline is active`,
});
}
// Processing status
if (processingCount > 0) {
insights.push({
type: 'action',
message: `${processingCount} tasks actively generating content - Check back soon for completed drafts`,
});
}
// Failed tasks
if (failedCount > 0) {
insights.push({
type: 'warning',
message: `${failedCount} tasks failed - Review errors and retry or adjust task parameters`,
});
}
// Completion success
if (completionRate >= 70 && completedCount >= 5) {
insights.push({
type: 'success',
message: `High completion rate (${completionRate}%) - ${completedCount} pieces of content ready for review`,
});
}
return insights;
}, [tasks, totalCount]);
// AI Function Logs state
@@ -424,11 +368,21 @@ export default function Tasks() {
return (
<>
<PageHeader
title="Content Queue"
description="Manage content tasks waiting for AI generation. Queue ideas here to create articles automatically."
badge={{ icon: <TaskIcon />, color: 'indigo' }}
breadcrumb="Writer / Queue"
workflowInsights={workflowInsights}
title="Queue"
description="Content writing queue"
badge={{ icon: <DocumentTextIcon />, color: 'blue' }}
breadcrumb="Writer"
actions={
<Link
to="/writer/content"
className="inline-flex items-center gap-2 px-3 py-1.5 text-sm font-medium text-white bg-brand-500 hover:bg-brand-600 rounded-lg transition-colors"
>
View Drafts
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
</svg>
</Link>
}
/>
<TablePageTemplate
columns={pageConfig.columns}