fix: Create missing ArticleList component and fix routing for content-factory
This commit is contained in:
90
frontend/src/components/admin/seo/ArticleList.tsx
Normal file
90
frontend/src/components/admin/seo/ArticleList.tsx
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
import React, { useState } from 'react';
|
||||||
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||||
|
import { Badge } from '@/components/ui/badge';
|
||||||
|
import { Button } from '@/components/ui/button';
|
||||||
|
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table';
|
||||||
|
|
||||||
|
interface Article {
|
||||||
|
id: number;
|
||||||
|
headline: string;
|
||||||
|
slug: string;
|
||||||
|
status: string;
|
||||||
|
is_published: boolean;
|
||||||
|
seo_score: number;
|
||||||
|
target_keyword: string;
|
||||||
|
campaign: { name: string } | null;
|
||||||
|
date_created: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
initialArticles?: Article[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function ArticleList({ initialArticles = [] }: Props) {
|
||||||
|
const [articles, setArticles] = useState(initialArticles);
|
||||||
|
|
||||||
|
const getStatusColor = (status: string, isPublished: boolean) => {
|
||||||
|
if (isPublished) return 'bg-green-600';
|
||||||
|
if (status === 'draft') return 'bg-slate-500';
|
||||||
|
if (status === 'review') return 'bg-yellow-500';
|
||||||
|
return 'bg-blue-500';
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card className="bg-slate-900 border-slate-800">
|
||||||
|
<CardHeader className="flex flex-row items-center justify-between">
|
||||||
|
<CardTitle className="text-white">Generated Articles</CardTitle>
|
||||||
|
<Button className="bg-blue-600 hover:bg-blue-700">
|
||||||
|
+ New Article
|
||||||
|
</Button>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<Table>
|
||||||
|
<TableHeader>
|
||||||
|
<TableRow className="border-slate-800 hover:bg-slate-900/50">
|
||||||
|
<TableHead className="text-slate-400">Headline</TableHead>
|
||||||
|
<TableHead className="text-slate-400">Keyword</TableHead>
|
||||||
|
<TableHead className="text-slate-400">Campaign</TableHead>
|
||||||
|
<TableHead className="text-slate-400">Status</TableHead>
|
||||||
|
<TableHead className="text-slate-400">Score</TableHead>
|
||||||
|
<TableHead className="text-right text-slate-400">Actions</TableHead>
|
||||||
|
</TableRow>
|
||||||
|
</TableHeader>
|
||||||
|
<TableBody>
|
||||||
|
{articles.length > 0 ? articles.map((article) => (
|
||||||
|
<TableRow key={article.id} className="border-slate-800 hover:bg-slate-800/50">
|
||||||
|
<TableCell className="font-medium text-white">
|
||||||
|
{article.headline}
|
||||||
|
<div className="text-xs text-slate-500">{article.slug}</div>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="text-slate-400">{article.target_keyword}</TableCell>
|
||||||
|
<TableCell className="text-slate-400">{article.campaign?.name || '-'}</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<Badge className={`${getStatusColor(article.status, article.is_published)} text-white border-0`}>
|
||||||
|
{article.is_published ? 'Published' : article.status}
|
||||||
|
</Badge>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<div className={`text-sm font-bold ${article.seo_score > 80 ? 'text-green-400' : 'text-yellow-400'}`}>
|
||||||
|
{article.seo_score || 0}
|
||||||
|
</div>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="text-right">
|
||||||
|
<Button variant="ghost" size="sm" className="text-blue-400 hover:text-blue-300">
|
||||||
|
Edit
|
||||||
|
</Button>
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
)) : (
|
||||||
|
<TableRow>
|
||||||
|
<TableCell colspan={6} className="text-center text-slate-500 py-8">
|
||||||
|
No articles found.
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
)}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,16 +1,9 @@
|
|||||||
---
|
---
|
||||||
import Layout from '@/layouts/AdminLayout.astro';
|
import Layout from '@/layouts/AdminLayout.astro';
|
||||||
import ContentFactoryDashboard from '@/components/admin/cartesian/ContentFactoryDashboard';
|
import ContentFactoryDashboard from '@/components/admin/content/ContentFactoryDashboard';
|
||||||
---
|
---
|
||||||
|
<Layout title="Factory Command Center">
|
||||||
<Layout title="Cartesian Content Factory">
|
<div class="p-8">
|
||||||
<div class="p-6">
|
<ContentFactoryDashboard client:load />
|
||||||
<div class="mb-8">
|
|
||||||
<h1 class="text-3xl font-bold text-slate-900">Cartesian Content Factory</h1>
|
|
||||||
<p class="text-slate-600">Mission Control for High-Volume Content Generation</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- React Application Root -->
|
|
||||||
<ContentFactoryDashboard client:only="react" />
|
|
||||||
</div>
|
</div>
|
||||||
</Layout>
|
</Layout>
|
||||||
|
|||||||
@@ -1,10 +1,22 @@
|
|||||||
```
|
|
||||||
---
|
---
|
||||||
import Layout from '@/layouts/AdminLayout.astro';
|
import Layout from '@/layouts/AdminLayout.astro';
|
||||||
import ArticleList from '@/components/admin/seo/ArticleList';
|
import ArticleList from '@/components/admin/seo/ArticleList';
|
||||||
|
import { getDirectusClient, readItems } from '@/lib/directus/client';
|
||||||
|
|
||||||
|
const directus = getDirectusClient();
|
||||||
|
const articles = await directus.request(readItems('generated_articles', {
|
||||||
|
fields: ['*', 'campaign.name'],
|
||||||
|
limit: 50,
|
||||||
|
sort: ['-date_created']
|
||||||
|
})).catch(() => []);
|
||||||
---
|
---
|
||||||
|
|
||||||
<Layout title="Generated Articles">
|
<Layout title="Generated Articles">
|
||||||
<ArticleList client:load />
|
<div class="p-8">
|
||||||
|
<div class="mb-6">
|
||||||
|
<h1 class="text-3xl font-bold text-white mb-2">Generated Articles</h1>
|
||||||
|
<p class="text-gray-400">Review and manage AI-generated SEO content.</p>
|
||||||
|
</div>
|
||||||
|
<ArticleList client:load initialArticles={articles} />
|
||||||
|
</div>
|
||||||
</Layout>
|
</Layout>
|
||||||
```
|
|
||||||
|
|||||||
Reference in New Issue
Block a user