diff --git a/frontend/src/pages/Planner/Clusters.tsx b/frontend/src/pages/Planner/Clusters.tsx
index bdabaed2..e7c3ed68 100644
--- a/frontend/src/pages/Planner/Clusters.tsx
+++ b/frontend/src/pages/Planner/Clusters.tsx
@@ -411,7 +411,6 @@ export default function Clusters() {
onClick: () => handleBulkAction('auto_generate_ideas', selectedIds),
variant: 'success',
}}
- getRowClassName={(row) => (row.ideas_count || 0) > 0 ? 'bg-success-50 dark:bg-success-500/10' : ''}
onFilterChange={(key, value) => {
const stringValue = value === null || value === undefined ? '' : String(value);
if (key === 'search') {
diff --git a/frontend/src/pages/Planner/Ideas.tsx b/frontend/src/pages/Planner/Ideas.tsx
index cb392835..cc8f492c 100644
--- a/frontend/src/pages/Planner/Ideas.tsx
+++ b/frontend/src/pages/Planner/Ideas.tsx
@@ -322,7 +322,6 @@ export default function Ideas() {
onClick: () => handleBulkAction('queue_to_writer', selectedIds),
variant: 'success',
}}
- getRowClassName={(row) => row.status === 'queued' || row.status === 'completed' ? 'bg-success-50 dark:bg-success-500/10' : ''}
onFilterChange={(key, value) => {
const stringValue = value === null || value === undefined ? '' : String(value);
if (key === 'search') {
diff --git a/frontend/src/pages/Planner/Keywords.tsx b/frontend/src/pages/Planner/Keywords.tsx
index d6afa5c2..6b98f5cb 100644
--- a/frontend/src/pages/Planner/Keywords.tsx
+++ b/frontend/src/pages/Planner/Keywords.tsx
@@ -603,7 +603,6 @@ export default function Keywords() {
onClick: () => handleBulkAction('auto_cluster', selectedIds),
variant: 'success',
}}
- getRowClassName={(row) => row.cluster_id ? 'bg-success-50 dark:bg-success-500/10' : ''}
onFilterChange={(key, value) => {
// Normalize value to string, preserving empty strings
const stringValue = value === null || value === undefined ? '' : String(value);
diff --git a/frontend/src/pages/Writer/Approved.tsx b/frontend/src/pages/Writer/Approved.tsx
index 3364de83..320fec77 100644
--- a/frontend/src/pages/Writer/Approved.tsx
+++ b/frontend/src/pages/Writer/Approved.tsx
@@ -37,7 +37,6 @@ export default function Approved() {
// Filter state - default to approved status
const [searchTerm, setSearchTerm] = useState('');
- const [statusFilter, setStatusFilter] = useState('approved'); // Default to approved
const [publishStatusFilter, setPublishStatusFilter] = useState('');
const [selectedIds, setSelectedIds] = useState
([]);
@@ -51,7 +50,7 @@ export default function Approved() {
const [sortDirection, setSortDirection] = useState<'asc' | 'desc'>('desc');
const [showContent, setShowContent] = useState(false);
- // Load content - filtered for approved status
+ // Load content - filtered for approved status (API still uses 'published' internally)
const loadContent = useCallback(async () => {
setLoading(true);
setShowContent(false);
@@ -60,7 +59,7 @@ export default function Approved() {
const filters: ContentFilters = {
...(searchTerm && { search: searchTerm }),
- status: 'approved', // Always filter for approved status
+ status: 'published', // Backend uses 'published' for approved content
page: currentPage,
page_size: pageSize,
ordering,
@@ -109,7 +108,7 @@ export default function Approved() {
setShowContent(true);
setLoading(false);
}
- }, [currentPage, statusFilter, publishStatusFilter, sortBy, sortDirection, searchTerm, pageSize, toast]);
+ }, [currentPage, publishStatusFilter, sortBy, sortDirection, searchTerm, pageSize, toast]);
useEffect(() => {
loadContent();
@@ -326,7 +325,6 @@ export default function Approved() {
onClick: () => handleBulkAction('bulk_publish_wordpress', selectedIds),
variant: 'success',
}}
- getRowClassName={(row) => row.external_id ? 'bg-success-50 dark:bg-success-500/10' : ''}
onFilterChange={(key: string, value: any) => {
if (key === 'search') {
setSearchTerm(value);
diff --git a/frontend/src/pages/Writer/Content.tsx b/frontend/src/pages/Writer/Content.tsx
index f95a8e3b..bac35a9d 100644
--- a/frontend/src/pages/Writer/Content.tsx
+++ b/frontend/src/pages/Writer/Content.tsx
@@ -242,7 +242,6 @@ export default function Content() {
status: statusFilter,
source: sourceFilter,
}}
- getRowClassName={(row) => row.status === 'review' || row.status === 'published' ? 'bg-success-50 dark:bg-success-500/10' : ''}
onFilterChange={(key: string, value: any) => {
if (key === 'search') {
setSearchTerm(value);
diff --git a/frontend/src/pages/Writer/Review.tsx b/frontend/src/pages/Writer/Review.tsx
index c04511af..75c4122e 100644
--- a/frontend/src/pages/Writer/Review.tsx
+++ b/frontend/src/pages/Writer/Review.tsx
@@ -416,7 +416,6 @@ export default function Review() {
onClick: () => handleBulkAction('bulk_approve', selectedIds),
variant: 'success',
}}
- getRowClassName={(row) => row.status === 'approved' ? 'bg-success-50 dark:bg-success-500/10' : ''}
onFilterChange={(key, value) => {
const stringValue = value === null || value === undefined ? '' : String(value);
if (key === 'search') {
diff --git a/frontend/src/pages/Writer/Tasks.tsx b/frontend/src/pages/Writer/Tasks.tsx
index bdad9afb..48512283 100644
--- a/frontend/src/pages/Writer/Tasks.tsx
+++ b/frontend/src/pages/Writer/Tasks.tsx
@@ -385,7 +385,6 @@ export default function Tasks() {
content_type: typeFilter,
source: sourceFilter,
}}
- getRowClassName={(row) => row.status === 'completed' ? 'bg-success-50 dark:bg-success-500/10' : ''}
onFilterChange={(key, value) => {
const stringValue = value === null || value === undefined ? '' : String(value);
if (key === 'search') {
diff --git a/frontend/src/templates/TablePageTemplate.tsx b/frontend/src/templates/TablePageTemplate.tsx
index 17c6313b..16cce994 100644
--- a/frontend/src/templates/TablePageTemplate.tsx
+++ b/frontend/src/templates/TablePageTemplate.tsx
@@ -22,6 +22,18 @@ import {
TableRow,
TableCell,
} from '../components/ui/table';
+
+// Helper function to format column key to display name
+// Converts snake_case/camelCase to Title Case (e.g., "content_type" -> "Content Type")
+const formatColumnKey = (key: string): string => {
+ return key
+ .replace(/_/g, ' ') // Replace underscores with spaces
+ .replace(/([a-z])([A-Z])/g, '$1 $2') // Add space before capital letters in camelCase
+ .split(' ')
+ .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
+ .join(' ');
+};
+
import Checkbox from '../components/form/input/Checkbox';
import Button from '../components/ui/button/Button';
import Input from '../components/form/input/InputField';
@@ -29,7 +41,8 @@ import SelectDropdown from '../components/form/SelectDropdown';
import { Dropdown } from '../components/ui/dropdown/Dropdown';
import { DropdownItem } from '../components/ui/dropdown/DropdownItem';
import AlertModal from '../components/ui/alert/AlertModal';
-import { ChevronDownIcon, MoreDotIcon, PlusIcon, ListIcon } from '../icons';
+import { ChevronDownIcon, MoreDotIcon, PlusIcon } from '../icons';
+import { FunnelIcon } from '@heroicons/react/24/outline';
import { useHeaderMetrics } from '../context/HeaderMetricsContext';
import { useToast } from '../components/ui/toast/ToastContainer';
import { getDeleteModalConfig } from '../config/pages/delete-modal.config';
@@ -571,7 +584,8 @@ export default function TablePageTemplate({
size="md"
onClick={primaryAction.onClick}
disabled={selectedIds.length === 0}
- variant={primaryAction.variant === 'success' ? 'success' : primaryAction.variant === 'warning' ? 'primary' : 'primary'}
+ variant="primary"
+ tone={primaryAction.variant === 'success' ? 'success' : primaryAction.variant === 'warning' ? 'warning' : 'brand'}
startIcon={primaryAction.icon}
className={selectedIds.length === 0 ? "opacity-50 cursor-not-allowed" : ""}
>
@@ -597,7 +611,8 @@ export default function TablePageTemplate({
}
}}
disabled={selectedIds.length === 0}
- variant={bulkActions[0].variant === 'success' ? 'success' : bulkActions[0].variant === 'danger' ? 'primary' : 'primary'}
+ variant="primary"
+ tone={bulkActions[0].variant === 'success' ? 'success' : bulkActions[0].variant === 'danger' ? 'danger' : 'brand'}
startIcon={bulkActions[0].icon}
className={selectedIds.length === 0 ? "opacity-50 cursor-not-allowed" : ""}
>
@@ -667,7 +682,7 @@ export default function TablePageTemplate({
variant="secondary"
size="md"
onClick={() => setShowFilters(!showFilters)}
- startIcon={}
+ startIcon={}
>
{showFilters ? 'Hide Filters' : 'Show Filters'}
@@ -800,22 +815,23 @@ export default function TablePageTemplate({
)}
{visibleColumnsList.map((column, colIndex) => {
const isLastColumn = colIndex === visibleColumnsList.length - 1;
+ const displayName = formatColumnKey(column.key);
return (
0 ? 'pr-16' : ''}`}
+ className={`px-5 py-3 font-medium text-gray-500 text-${column.align || 'start'} text-[11px] dark:text-gray-400 ${column.sortable ? 'cursor-pointer hover:text-gray-700 dark:hover:text-gray-300' : ''} ${isLastColumn && rowActions.length > 0 ? 'pr-16' : ''}`}
>
{column.sortable ? (
handleSort(column)} className="flex items-center">
- {column.label}
+ {displayName}
{getSortIcon(column)}
) : (
<>
- {column.label}
+ {displayName}
{getSortIcon(column)}
>
)}
@@ -825,7 +841,7 @@ export default function TablePageTemplate({
({
key: col.key,
- label: col.label,
+ label: formatColumnKey(col.key),
defaultVisible: col.defaultVisible !== false,
}))}
visibleColumns={visibleColumns}