mpre ui fixes

This commit is contained in:
IGNY8 VPS (Salman)
2025-12-27 08:00:09 +00:00
parent 4482d2f4c4
commit 034c640601
17 changed files with 352 additions and 158 deletions

View File

@@ -305,7 +305,7 @@ export default function Approved() {
return (
<>
<PageHeader
title="Approved"
title="Content Approved"
badge={{ icon: <CheckCircleIcon />, color: 'green' }}
parent="Writer"
/>

View File

@@ -25,6 +25,7 @@ import { useProgressModal } from '../../hooks/useProgressModal';
import PageHeader from '../../components/common/PageHeader';
import ModuleMetricsFooter, { MetricItem, ProgressMetric } from '../../components/dashboard/ModuleMetricsFooter';
import { PencilSquareIcon } from '@heroicons/react/24/outline';
import StatusMetricsCard from '../../components/common/StatusMetricsCard';
export default function Content() {
const toast = useToast();
@@ -55,6 +56,22 @@ export default function Content() {
const progressModal = useProgressModal();
const hasReloadedRef = useRef(false);
// Review count state
const [reviewCount, setReviewCount] = useState(0);
// Load review count
useEffect(() => {
const loadReviewCount = async () => {
try {
const data = await fetchContent({ status: 'review', page_size: 1 });
setReviewCount(data.count || 0);
} catch (error) {
console.error('Error fetching review count:', error);
}
};
loadReviewCount();
}, []);
// Load content - wrapped in useCallback
const loadContent = useCallback(async () => {
setLoading(true);
@@ -227,7 +244,7 @@ export default function Content() {
return (
<>
<PageHeader
title="Drafts"
title="Content Drafts"
badge={{ icon: <PencilSquareIcon />, color: 'orange' }}
parent="Writer"
/>
@@ -274,26 +291,22 @@ export default function Content() {
onBulkDelete={handleBulkDelete}
getItemDisplayName={(row: ContentType) => row.title || `Content #${row.id}`}
statusExplainer={
<div className="text-xs text-gray-600 dark:text-gray-400 space-y-1">
<div className="font-medium text-gray-700 dark:text-gray-300">
Currently Generated (Draft): {content.filter(c => c.status === 'draft').length}
</div>
<div>
Image Prompts: {content.filter(c => c.has_image_prompts).length}/{content.length}
</div>
<div>
Images Generated: {content.filter(c => c.has_generated_images).length}/{content.length}
</div>
<div className="pt-2 border-t border-gray-200 dark:border-gray-700 mt-2">
<Link
to="/writer/review"
className="text-brand-500 hover:text-brand-600 flex items-center gap-1"
>
<span>Review ({content.filter(c => c.status === 'review').length})</span>
<ArrowRightIcon className="w-3 h-3" />
</Link>
</div>
</div>
<StatusMetricsCard
title="Content Drafts"
color="orange"
icon={<PencilSquareIcon className="w-5 h-5" />}
count={totalCount}
subtitle="draft content items"
metrics={[
{ label: 'Image Prompts', value: `${content.filter(c => c.has_image_prompts).length}/${content.length}` },
{ label: 'Images Generated', value: `${content.filter(c => c.has_generated_images).length}/${content.length}` },
]}
reviewCount={reviewCount}
actionButton={{
label: 'Review',
href: '/writer/review',
}}
/>
}
/>

View File

@@ -17,6 +17,7 @@ import {
fetchAPI,
deleteContent,
bulkDeleteContent,
fetchContent,
} from '../../services/api';
import { useToast } from '../../components/ui/toast/ToastContainer';
import { FileIcon, DownloadIcon, ArrowRightIcon } from '../../icons';
@@ -26,6 +27,7 @@ import ImageQueueModal, { ImageQueueItem } from '../../components/common/ImageQu
import SingleRecordStatusUpdateModal from '../../components/common/SingleRecordStatusUpdateModal';
import PageHeader from '../../components/common/PageHeader';
import { Modal } from '../../components/ui/modal';
import StatusMetricsCard from '../../components/common/StatusMetricsCard';
export default function Images() {
const toast = useToast();
@@ -68,6 +70,22 @@ export default function Images() {
const [isImageModalOpen, setIsImageModalOpen] = useState(false);
const [modalImageUrl, setModalImageUrl] = useState<string | null>(null);
// Review count state
const [reviewCount, setReviewCount] = useState(0);
// Load review count
useEffect(() => {
const loadReviewCount = async () => {
try {
const data = await fetchContent({ status: 'review', page_size: 1 });
setReviewCount(data.count || 0);
} catch (error) {
console.error('Error fetching review count:', error);
}
};
loadReviewCount();
}, []);
// Load images - wrapped in useCallback
const loadImages = useCallback(async () => {
setLoading(true);
@@ -451,7 +469,7 @@ export default function Images() {
return (
<>
<PageHeader
title="Images"
title="Content Images"
badge={{ icon: <PhotoIcon />, color: 'pink' }}
parent="Writer"
/>
@@ -516,26 +534,22 @@ export default function Images() {
}}
onRowAction={handleRowAction}
statusExplainer={
<div className="text-xs text-gray-600 dark:text-gray-400 space-y-1">
<div className="font-medium text-gray-700 dark:text-gray-300">
Content Images Status
</div>
<div>
Need Images: {images.filter(i => i.overall_status === 'pending').length}
</div>
<div>
Images Complete: {images.filter(i => i.overall_status === 'complete').length}
</div>
<div className="pt-2 border-t border-gray-200 dark:border-gray-700 mt-2">
<Link
to="/writer/review"
className="text-brand-500 hover:text-brand-600 flex items-center gap-1"
>
<span>Go to Review</span>
<ArrowRightIcon className="w-3 h-3" />
</Link>
</div>
</div>
<StatusMetricsCard
title="Content Images"
color="pink"
icon={<PhotoIcon className="w-5 h-5" />}
count={totalCount}
subtitle="content items with images"
metrics={[
{ label: 'Need Images', value: images.filter(i => i.overall_status === 'pending').length },
{ label: 'Images Complete', value: images.filter(i => i.overall_status === 'complete').length },
]}
reviewCount={reviewCount}
actionButton={{
label: 'Review',
href: '/writer/review',
}}
/>
}
/>
<ImageQueueModal

View File

@@ -21,6 +21,7 @@ import { useSectorStore } from '../../store/sectorStore';
import { usePageSizeStore } from '../../store/pageSizeStore';
import PageHeader from '../../components/common/PageHeader';
import ModuleMetricsFooter from '../../components/dashboard/ModuleMetricsFooter';
import StatusMetricsCard from '../../components/common/StatusMetricsCard';
export default function Review() {
const toast = useToast();
@@ -397,7 +398,7 @@ export default function Review() {
return (
<>
<PageHeader
title="Review"
title="Content Review"
badge={{ icon: <ClipboardDocumentCheckIcon />, color: 'emerald' }}
parent="Writer"
/>
@@ -454,11 +455,17 @@ export default function Review() {
}}
onRowAction={handleRowAction}
statusExplainer={
<div className="text-xs text-gray-600 dark:text-gray-400 space-y-1">
<div className="font-medium text-gray-700 dark:text-gray-300">
Approve {totalCount} content pages/articles awaiting approval
</div>
</div>
<StatusMetricsCard
title="In Review"
color="emerald"
icon={<ClipboardDocumentCheckIcon className="w-5 h-5" />}
count={totalCount}
subtitle="awaiting approval"
actionButton={{
label: 'Approved',
href: '/writer/approved',
}}
/>
}
/>
<ModuleMetricsFooter

View File

@@ -4,6 +4,7 @@
*/
import { useState, useEffect, useCallback, useRef, useMemo } from 'react';
import { Link } from 'react-router-dom';
import TablePageTemplate from '../../templates/TablePageTemplate';
import {
fetchTasks,
@@ -19,6 +20,7 @@ import {
TaskCreateData,
fetchClusters,
Cluster,
fetchContent,
} from '../../services/api';
import FormModal from '../../components/common/FormModal';
import ProgressModal from '../../components/common/ProgressModal';
@@ -31,6 +33,7 @@ import { usePageSizeStore } from '../../store/pageSizeStore';
import PageHeader from '../../components/common/PageHeader';
import ModuleMetricsFooter, { MetricItem, ProgressMetric } from '../../components/dashboard/ModuleMetricsFooter';
import { DocumentTextIcon } from '@heroicons/react/24/outline';
import StatusMetricsCard from '../../components/common/StatusMetricsCard';
export default function Tasks() {
const toast = useToast();
@@ -79,11 +82,27 @@ export default function Tasks() {
// Progress modal for AI functions
const progressModal = useProgressModal();
// Review count state
const [reviewCount, setReviewCount] = useState(0);
// AI Function Logs state
const hasReloadedRef = useRef<boolean>(false);
// Load review count
useEffect(() => {
const loadReviewCount = async () => {
try {
const data = await fetchContent({ status: 'review', page_size: 1 });
setReviewCount(data.count || 0);
} catch (error) {
console.error('Error fetching review count:', error);
}
};
loadReviewCount();
}, []);
// Load clusters for filter dropdown
@@ -367,7 +386,7 @@ export default function Tasks() {
return (
<>
<PageHeader
title="Queue"
title="Content Queue"
badge={{ icon: <DocumentTextIcon />, color: 'blue' }}
parent="Writer"
/>
@@ -417,12 +436,6 @@ export default function Tasks() {
setIsEditMode(true);
setIsModalOpen(true);
}}
onCreate={() => {
resetForm();
setIsModalOpen(true);
}}
createLabel="Add Task"
onCreateIcon={<PlusIcon />}
onDelete={async (id: number) => {
await deleteTask(id);
loadTasks();
@@ -473,6 +486,24 @@ export default function Tasks() {
setTypeFilter('');
setCurrentPage(1);
}}
statusExplainer={
<StatusMetricsCard
title="In Queue"
color="blue"
icon={<DocumentTextIcon className="w-5 h-5" />}
count={totalCount}
subtitle="content items queued"
metrics={[
{ label: 'Queued', value: tasks.filter(t => t.status === 'queued').length },
{ label: 'Processing', value: tasks.filter(t => t.status === 'in_progress').length },
]}
reviewCount={reviewCount}
actionButton={{
label: 'Review',
href: '/writer/review',
}}
/>
}
/>
{/* Module Metrics Footer - Pipeline Style with Cross-Module Links */}