thinker and automation dashboards
This commit is contained in:
484
frontend/src/pages/Automation/Dashboard.tsx
Normal file
484
frontend/src/pages/Automation/Dashboard.tsx
Normal file
@@ -0,0 +1,484 @@
|
||||
import { useEffect, useState, lazy, Suspense } from "react";
|
||||
import { Link, useNavigate } from "react-router";
|
||||
import PageMeta from "../../components/common/PageMeta";
|
||||
import ComponentCard from "../../components/common/ComponentCard";
|
||||
import { ProgressBar } from "../../components/ui/progress";
|
||||
import { ApexOptions } from "apexcharts";
|
||||
import EnhancedMetricCard from "../../components/dashboard/EnhancedMetricCard";
|
||||
import PageHeader from "../../components/common/PageHeader";
|
||||
|
||||
const Chart = lazy(() => import("react-apexcharts").then((mod) => ({ default: mod.default })));
|
||||
|
||||
import {
|
||||
BoltIcon,
|
||||
ClockIcon,
|
||||
CheckCircleIcon,
|
||||
ArrowRightIcon,
|
||||
CalendarIcon,
|
||||
ListIcon,
|
||||
GroupIcon,
|
||||
FileTextIcon,
|
||||
ArrowUpIcon,
|
||||
ArrowDownIcon,
|
||||
PaperPlaneIcon,
|
||||
CloseIcon,
|
||||
FileIcon,
|
||||
} from "../../icons";
|
||||
import { useSiteStore } from "../../store/siteStore";
|
||||
import { useSectorStore } from "../../store/sectorStore";
|
||||
|
||||
interface AutomationStats {
|
||||
activeWorkflows: number;
|
||||
scheduledTasks: number;
|
||||
completedToday: number;
|
||||
successRate: number;
|
||||
automationCoverage: {
|
||||
keywords: boolean;
|
||||
clustering: boolean;
|
||||
ideas: boolean;
|
||||
tasks: boolean;
|
||||
content: boolean;
|
||||
images: boolean;
|
||||
publishing: boolean;
|
||||
};
|
||||
recentActivity: Array<{
|
||||
id: number;
|
||||
type: string;
|
||||
status: string;
|
||||
timestamp: Date;
|
||||
itemsProcessed: number;
|
||||
}>;
|
||||
}
|
||||
|
||||
export default function AutomationDashboard() {
|
||||
const navigate = useNavigate();
|
||||
const { activeSite } = useSiteStore();
|
||||
const { activeSector } = useSectorStore();
|
||||
|
||||
const [stats, setStats] = useState<AutomationStats | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [lastUpdated, setLastUpdated] = useState<Date>(new Date());
|
||||
|
||||
// Mock data for now - will be replaced with real API calls
|
||||
useEffect(() => {
|
||||
const fetchData = async () => {
|
||||
setLoading(true);
|
||||
// Simulate API call
|
||||
await new Promise((resolve) => setTimeout(resolve, 500));
|
||||
|
||||
setStats({
|
||||
activeWorkflows: 3,
|
||||
scheduledTasks: 12,
|
||||
completedToday: 47,
|
||||
successRate: 94.5,
|
||||
automationCoverage: {
|
||||
keywords: true,
|
||||
clustering: true,
|
||||
ideas: true,
|
||||
tasks: false,
|
||||
content: true,
|
||||
images: true,
|
||||
publishing: false,
|
||||
},
|
||||
recentActivity: [
|
||||
{
|
||||
id: 1,
|
||||
type: "Content Generation",
|
||||
status: "completed",
|
||||
timestamp: new Date(Date.now() - 15 * 60 * 1000),
|
||||
itemsProcessed: 5,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
type: "Image Generation",
|
||||
status: "completed",
|
||||
timestamp: new Date(Date.now() - 45 * 60 * 1000),
|
||||
itemsProcessed: 8,
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
type: "Keyword Clustering",
|
||||
status: "completed",
|
||||
timestamp: new Date(Date.now() - 2 * 60 * 60 * 1000),
|
||||
itemsProcessed: 12,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
setLastUpdated(new Date());
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
fetchData();
|
||||
}, [activeSite, activeSector]);
|
||||
|
||||
const automationWorkflows = [
|
||||
{
|
||||
id: 1,
|
||||
name: "Full Pipeline Automation",
|
||||
description: "Keywords → Clusters → Ideas → Tasks → Content → Images → Publish",
|
||||
status: "active",
|
||||
schedule: "Every 6 hours",
|
||||
lastRun: "2 hours ago",
|
||||
nextRun: "4 hours",
|
||||
coverage: 85,
|
||||
icon: PaperPlaneIcon,
|
||||
color: "from-[#5d4ae3] to-[#3a2f94]",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: "Writer Workflow",
|
||||
description: "Tasks → Content → Images → Publishing",
|
||||
status: "active",
|
||||
schedule: "Every 3 hours",
|
||||
lastRun: "1 hour ago",
|
||||
nextRun: "2 hours",
|
||||
coverage: 92,
|
||||
icon: FileTextIcon,
|
||||
color: "from-[#0bbf87] to-[#08966b]",
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: "Planner Workflow",
|
||||
description: "Keywords → Clusters → Ideas",
|
||||
status: "active",
|
||||
schedule: "Every 6 hours",
|
||||
lastRun: "3 hours ago",
|
||||
nextRun: "3 hours",
|
||||
coverage: 78,
|
||||
icon: ListIcon,
|
||||
color: "from-[#0693e3] to-[#0472b8]",
|
||||
},
|
||||
];
|
||||
|
||||
const automationSteps = [
|
||||
{
|
||||
step: "Keywords",
|
||||
enabled: true,
|
||||
description: "Auto-add keywords from opportunities",
|
||||
path: "/planner/keyword-opportunities",
|
||||
icon: ListIcon,
|
||||
},
|
||||
{
|
||||
step: "Clustering",
|
||||
enabled: true,
|
||||
description: "Auto-cluster keywords into groups",
|
||||
path: "/planner/clusters",
|
||||
icon: GroupIcon,
|
||||
},
|
||||
{
|
||||
step: "Ideas",
|
||||
enabled: true,
|
||||
description: "Auto-generate content ideas from clusters",
|
||||
path: "/planner/ideas",
|
||||
icon: BoltIcon,
|
||||
},
|
||||
{
|
||||
step: "Tasks",
|
||||
enabled: false,
|
||||
description: "Auto-create tasks from ideas",
|
||||
path: "/writer/tasks",
|
||||
icon: CheckCircleIcon,
|
||||
},
|
||||
{
|
||||
step: "Content",
|
||||
enabled: true,
|
||||
description: "Auto-generate content from tasks",
|
||||
path: "/writer/content",
|
||||
icon: FileTextIcon,
|
||||
},
|
||||
{
|
||||
step: "Images",
|
||||
enabled: true,
|
||||
description: "Auto-generate images for content",
|
||||
path: "/writer/images",
|
||||
icon: FileIcon,
|
||||
},
|
||||
{
|
||||
step: "Publishing",
|
||||
enabled: false,
|
||||
description: "Auto-publish content to WordPress",
|
||||
path: "/writer/published",
|
||||
icon: PaperPlaneIcon,
|
||||
},
|
||||
];
|
||||
|
||||
const chartOptions: ApexOptions = {
|
||||
chart: {
|
||||
type: "line",
|
||||
height: 300,
|
||||
toolbar: { show: false },
|
||||
zoom: { enabled: false },
|
||||
},
|
||||
stroke: {
|
||||
curve: "smooth",
|
||||
width: 3,
|
||||
},
|
||||
xaxis: {
|
||||
categories: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
|
||||
labels: { style: { colors: "#6b7280" } },
|
||||
},
|
||||
yaxis: {
|
||||
labels: { style: { colors: "#6b7280" } },
|
||||
},
|
||||
legend: {
|
||||
position: "top",
|
||||
labels: { colors: "#6b7280" },
|
||||
},
|
||||
colors: ["#0693e3", "#0bbf87", "#5d4ae3"],
|
||||
grid: {
|
||||
borderColor: "#e5e7eb",
|
||||
},
|
||||
};
|
||||
|
||||
const chartSeries = [
|
||||
{
|
||||
name: "Automated",
|
||||
data: [12, 19, 15, 25, 22, 18, 24],
|
||||
},
|
||||
{
|
||||
name: "Manual",
|
||||
data: [5, 8, 6, 10, 9, 7, 11],
|
||||
},
|
||||
{
|
||||
name: "Failed",
|
||||
data: [1, 2, 1, 2, 1, 2, 1],
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<>
|
||||
<PageMeta title="Automation Dashboard - IGNY8" description="Manage and monitor automation workflows" />
|
||||
<PageHeader title="Automation Dashboard" />
|
||||
|
||||
<div className="space-y-6">
|
||||
{/* Key Metrics */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
|
||||
<EnhancedMetricCard
|
||||
title="Active Workflows"
|
||||
value={stats?.activeWorkflows || 0}
|
||||
icon={BoltIcon}
|
||||
trend={{ value: 0, isPositive: true }}
|
||||
color="from-[#5d4ae3] to-[#3a2f94]"
|
||||
loading={loading}
|
||||
/>
|
||||
<EnhancedMetricCard
|
||||
title="Scheduled Tasks"
|
||||
value={stats?.scheduledTasks || 0}
|
||||
icon={CalendarIcon}
|
||||
trend={{ value: 0, isPositive: true }}
|
||||
color="from-[#0693e3] to-[#0472b8]"
|
||||
loading={loading}
|
||||
/>
|
||||
<EnhancedMetricCard
|
||||
title="Completed Today"
|
||||
value={stats?.completedToday || 0}
|
||||
icon={CheckCircleIcon}
|
||||
trend={{ value: 0, isPositive: true }}
|
||||
color="from-[#0bbf87] to-[#08966b]"
|
||||
loading={loading}
|
||||
/>
|
||||
<EnhancedMetricCard
|
||||
title="Success Rate"
|
||||
value={`${stats?.successRate || 0}%`}
|
||||
icon={PaperPlaneIcon}
|
||||
trend={{ value: 0, isPositive: true }}
|
||||
color="from-[#ff7a00] to-[#cc5f00]"
|
||||
loading={loading}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Automation Workflows */}
|
||||
<ComponentCard title="Automation Workflows" desc="Manage your automated content pipelines">
|
||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
||||
{automationWorkflows.map((workflow) => {
|
||||
const Icon = workflow.icon;
|
||||
return (
|
||||
<div
|
||||
key={workflow.id}
|
||||
className="rounded-2xl border-2 border-slate-200 bg-white p-6 hover:shadow-lg transition-all"
|
||||
>
|
||||
<div className="flex items-start justify-between mb-4">
|
||||
<div className={`inline-flex size-12 rounded-xl bg-gradient-to-br ${workflow.color} items-center justify-center text-white shadow-lg`}>
|
||||
<Icon className="h-6 w-6" />
|
||||
</div>
|
||||
<span className={`inline-flex items-center px-3 py-1 rounded-full text-xs font-semibold ${
|
||||
workflow.status === "active"
|
||||
? "bg-green-100 text-green-700"
|
||||
: "bg-gray-100 text-gray-700"
|
||||
}`}>
|
||||
{workflow.status}
|
||||
</span>
|
||||
</div>
|
||||
<h3 className="text-lg font-bold text-slate-900 mb-2">{workflow.name}</h3>
|
||||
<p className="text-sm text-slate-600 mb-4">{workflow.description}</p>
|
||||
<div className="space-y-2 mb-4">
|
||||
<div className="flex items-center justify-between text-xs text-slate-600">
|
||||
<span>Schedule:</span>
|
||||
<span className="font-semibold">{workflow.schedule}</span>
|
||||
</div>
|
||||
<div className="flex items-center justify-between text-xs text-slate-600">
|
||||
<span>Last Run:</span>
|
||||
<span>{workflow.lastRun}</span>
|
||||
</div>
|
||||
<div className="flex items-center justify-between text-xs text-slate-600">
|
||||
<span>Next Run:</span>
|
||||
<span className="font-semibold text-[#0693e3]">{workflow.nextRun}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mb-4">
|
||||
<div className="flex items-center justify-between text-xs text-slate-600 mb-1">
|
||||
<span>Coverage</span>
|
||||
<span className="font-semibold">{workflow.coverage}%</span>
|
||||
</div>
|
||||
<ProgressBar value={workflow.coverage} className="h-2" />
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<button className="flex-1 inline-flex items-center justify-center gap-2 rounded-lg bg-slate-100 text-slate-700 px-4 py-2 text-sm font-semibold hover:bg-slate-200 transition">
|
||||
<CloseIcon className="h-4 w-4" />
|
||||
Pause
|
||||
</button>
|
||||
<button className="flex-1 inline-flex items-center justify-center gap-2 rounded-lg bg-gradient-to-r from-[#0693e3] to-[#0472b8] text-white px-4 py-2 text-sm font-semibold hover:shadow-lg transition">
|
||||
<PaperPlaneIcon className="h-4 w-4" />
|
||||
Run Now
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</ComponentCard>
|
||||
|
||||
{/* Automation Steps Configuration */}
|
||||
<ComponentCard title="Automation Steps" desc="Configure which steps are automated">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
|
||||
{automationSteps.map((step, index) => {
|
||||
const Icon = step.icon;
|
||||
const isEnabled = stats?.automationCoverage[step.step.toLowerCase() as keyof typeof stats.automationCoverage] || false;
|
||||
return (
|
||||
<Link
|
||||
key={step.step}
|
||||
to={step.path}
|
||||
className="rounded-xl border-2 border-slate-200 bg-white p-5 hover:shadow-lg transition-all group"
|
||||
>
|
||||
<div className="flex items-center justify-between mb-3">
|
||||
<div className={`inline-flex size-10 rounded-lg bg-gradient-to-br ${
|
||||
isEnabled
|
||||
? "from-[#0bbf87] to-[#08966b]"
|
||||
: "from-slate-300 to-slate-400"
|
||||
} items-center justify-center text-white shadow-md`}>
|
||||
<Icon className="h-5 w-5" />
|
||||
</div>
|
||||
<div className={`size-5 rounded-full border-2 flex items-center justify-center ${
|
||||
isEnabled
|
||||
? "border-[#0bbf87] bg-[#0bbf87]"
|
||||
: "border-slate-300 bg-white"
|
||||
}`}>
|
||||
{isEnabled && <CheckCircleIcon className="h-3 w-3 text-white" />}
|
||||
</div>
|
||||
</div>
|
||||
<h4 className="font-semibold text-slate-900 mb-1">{step.step}</h4>
|
||||
<p className="text-xs text-slate-600">{step.description}</p>
|
||||
<div className="mt-3 flex items-center gap-1 text-xs text-[#0693e3] opacity-0 group-hover:opacity-100 transition">
|
||||
<span>Configure</span>
|
||||
<ArrowRightIcon className="h-3 w-3" />
|
||||
</div>
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</ComponentCard>
|
||||
|
||||
{/* Activity Chart */}
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
||||
<ComponentCard title="Automation Activity" desc="Last 7 days of automation activity">
|
||||
<Suspense fallback={<div className="h-[300px] flex items-center justify-center">Loading chart...</div>}>
|
||||
<Chart options={chartOptions} series={chartSeries} type="line" height={300} />
|
||||
</Suspense>
|
||||
</ComponentCard>
|
||||
|
||||
{/* Recent Activity */}
|
||||
<ComponentCard title="Recent Activity" desc="Latest automation executions">
|
||||
<div className="space-y-4">
|
||||
{stats?.recentActivity.map((activity) => (
|
||||
<div
|
||||
key={activity.id}
|
||||
className="flex items-center gap-4 p-4 rounded-lg border border-slate-200 bg-white"
|
||||
>
|
||||
<div className="size-10 rounded-lg bg-gradient-to-br from-[#0693e3] to-[#0472b8] flex items-center justify-center text-white shadow-md">
|
||||
<BoltIcon className="h-5 w-5" />
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<div className="flex items-center justify-between mb-1">
|
||||
<h4 className="font-semibold text-slate-900">{activity.type}</h4>
|
||||
<span className={`text-xs px-2 py-1 rounded-full ${
|
||||
activity.status === "completed"
|
||||
? "bg-green-100 text-green-700"
|
||||
: "bg-yellow-100 text-yellow-700"
|
||||
}`}>
|
||||
{activity.status}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-4 text-xs text-slate-600">
|
||||
<span>{activity.itemsProcessed} items processed</span>
|
||||
<span>•</span>
|
||||
<span>{new Date(activity.timestamp).toLocaleTimeString()}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</ComponentCard>
|
||||
</div>
|
||||
|
||||
{/* Quick Actions */}
|
||||
<ComponentCard title="Quick Actions" desc="Manually trigger automation workflows">
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||||
<button
|
||||
onClick={() => navigate("/planner/keyword-opportunities")}
|
||||
className="flex items-center gap-4 p-6 rounded-xl border-2 border-slate-200 bg-white hover:border-[#0693e3] hover:shadow-lg transition-all group"
|
||||
>
|
||||
<div className="size-12 rounded-xl bg-gradient-to-br from-[#0693e3] to-[#0472b8] flex items-center justify-center text-white shadow-lg">
|
||||
<ListIcon className="h-6 w-6" />
|
||||
</div>
|
||||
<div className="flex-1 text-left">
|
||||
<h4 className="font-semibold text-slate-900 mb-1">Run Planner Workflow</h4>
|
||||
<p className="text-sm text-slate-600">Keywords → Clusters → Ideas</p>
|
||||
</div>
|
||||
<ArrowRightIcon className="h-5 w-5 text-slate-400 group-hover:text-[#0693e3] transition" />
|
||||
</button>
|
||||
|
||||
<button
|
||||
onClick={() => navigate("/writer/tasks")}
|
||||
className="flex items-center gap-4 p-6 rounded-xl border-2 border-slate-200 bg-white hover:border-[#0bbf87] hover:shadow-lg transition-all group"
|
||||
>
|
||||
<div className="size-12 rounded-xl bg-gradient-to-br from-[#0bbf87] to-[#08966b] flex items-center justify-center text-white shadow-lg">
|
||||
<FileTextIcon className="h-6 w-6" />
|
||||
</div>
|
||||
<div className="flex-1 text-left">
|
||||
<h4 className="font-semibold text-slate-900 mb-1">Run Writer Workflow</h4>
|
||||
<p className="text-sm text-slate-600">Tasks → Content → Images</p>
|
||||
</div>
|
||||
<ArrowRightIcon className="h-5 w-5 text-slate-400 group-hover:text-[#0bbf87] transition" />
|
||||
</button>
|
||||
|
||||
<button
|
||||
onClick={() => navigate("/writer/published")}
|
||||
className="flex items-center gap-4 p-6 rounded-xl border-2 border-slate-200 bg-white hover:border-[#5d4ae3] hover:shadow-lg transition-all group"
|
||||
>
|
||||
<div className="size-12 rounded-xl bg-gradient-to-br from-[#5d4ae3] to-[#3a2f94] flex items-center justify-center text-white shadow-lg">
|
||||
<PaperPlaneIcon className="h-6 w-6" />
|
||||
</div>
|
||||
<div className="flex-1 text-left">
|
||||
<h4 className="font-semibold text-slate-900 mb-1">Run Full Pipeline</h4>
|
||||
<p className="text-sm text-slate-600">Complete end-to-end automation</p>
|
||||
</div>
|
||||
<ArrowRightIcon className="h-5 w-5 text-slate-400 group-hover:text-[#5d4ae3] transition" />
|
||||
</button>
|
||||
</div>
|
||||
</ComponentCard>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,22 +1,392 @@
|
||||
import { useEffect, useState, lazy, Suspense } from "react";
|
||||
import { Link, useNavigate } from "react-router";
|
||||
import PageMeta from "../../components/common/PageMeta";
|
||||
import ComponentCard from "../../components/common/ComponentCard";
|
||||
import { ProgressBar } from "../../components/ui/progress";
|
||||
import { ApexOptions } from "apexcharts";
|
||||
import EnhancedMetricCard from "../../components/dashboard/EnhancedMetricCard";
|
||||
import PageHeader from "../../components/common/PageHeader";
|
||||
|
||||
const Chart = lazy(() => import("react-apexcharts").then((mod) => ({ default: mod.default })));
|
||||
|
||||
import {
|
||||
BoltIcon,
|
||||
FileTextIcon,
|
||||
UserIcon,
|
||||
ShootingStarIcon,
|
||||
CheckCircleIcon,
|
||||
ArrowRightIcon,
|
||||
PlusIcon,
|
||||
PencilIcon,
|
||||
ClockIcon,
|
||||
PieChartIcon,
|
||||
DocsIcon,
|
||||
} from "../../icons";
|
||||
import { useSiteStore } from "../../store/siteStore";
|
||||
import { useSectorStore } from "../../store/sectorStore";
|
||||
|
||||
interface ThinkerStats {
|
||||
totalPrompts: number;
|
||||
activeProfiles: number;
|
||||
strategies: number;
|
||||
usageThisMonth: number;
|
||||
}
|
||||
|
||||
export default function ThinkerDashboard() {
|
||||
const navigate = useNavigate();
|
||||
const { activeSite } = useSiteStore();
|
||||
const { activeSector } = useSectorStore();
|
||||
|
||||
const [stats, setStats] = useState<ThinkerStats | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [lastUpdated, setLastUpdated] = useState<Date>(new Date());
|
||||
|
||||
// Mock data for now - will be replaced with real API calls
|
||||
useEffect(() => {
|
||||
const fetchData = async () => {
|
||||
setLoading(true);
|
||||
// Simulate API call
|
||||
await new Promise((resolve) => setTimeout(resolve, 500));
|
||||
|
||||
setStats({
|
||||
totalPrompts: 24,
|
||||
activeProfiles: 8,
|
||||
strategies: 12,
|
||||
usageThisMonth: 342,
|
||||
});
|
||||
|
||||
setLastUpdated(new Date());
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
fetchData();
|
||||
}, [activeSite, activeSector]);
|
||||
|
||||
const thinkerModules = [
|
||||
{
|
||||
title: "Prompt Library",
|
||||
description: "Centralized prompt templates and AI instructions",
|
||||
icon: FileTextIcon,
|
||||
color: "from-[#ff7a00] to-[#cc5f00]",
|
||||
path: "/thinker/prompts",
|
||||
count: stats?.totalPrompts || 0,
|
||||
status: "active",
|
||||
},
|
||||
{
|
||||
title: "Author Profiles",
|
||||
description: "Voice templates and writing style guides",
|
||||
icon: UserIcon,
|
||||
color: "from-[#0693e3] to-[#0472b8]",
|
||||
path: "/thinker/profiles",
|
||||
count: stats?.activeProfiles || 0,
|
||||
status: "active",
|
||||
},
|
||||
{
|
||||
title: "Content Strategies",
|
||||
description: "Brand playbooks and content frameworks",
|
||||
icon: ShootingStarIcon,
|
||||
color: "from-[#5d4ae3] to-[#3a2f94]",
|
||||
path: "/thinker/strategies",
|
||||
count: stats?.strategies || 0,
|
||||
status: "active",
|
||||
},
|
||||
{
|
||||
title: "Governance",
|
||||
description: "Track AI usage, compliance, and version control",
|
||||
icon: PieChartIcon,
|
||||
color: "from-[#0bbf87] to-[#08966b]",
|
||||
path: "/thinker/governance",
|
||||
count: 0,
|
||||
status: "coming-soon",
|
||||
},
|
||||
];
|
||||
|
||||
const recentPrompts = [
|
||||
{
|
||||
id: 1,
|
||||
name: "Long-form Article Template",
|
||||
category: "Content Generation",
|
||||
usage: 45,
|
||||
lastUsed: "2 hours ago",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: "SEO-Optimized Brief",
|
||||
category: "Content Planning",
|
||||
usage: 32,
|
||||
lastUsed: "5 hours ago",
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: "Brand Voice - Technical",
|
||||
category: "Author Profile",
|
||||
usage: 28,
|
||||
lastUsed: "1 day ago",
|
||||
},
|
||||
];
|
||||
|
||||
const chartOptions: ApexOptions = {
|
||||
chart: {
|
||||
type: "donut",
|
||||
height: 300,
|
||||
},
|
||||
labels: ["Content Generation", "Content Planning", "Image Prompts", "Other"],
|
||||
colors: ["#ff7a00", "#0693e3", "#5d4ae3", "#0bbf87"],
|
||||
legend: {
|
||||
position: "bottom",
|
||||
labels: { colors: "#6b7280" },
|
||||
},
|
||||
dataLabels: {
|
||||
enabled: true,
|
||||
formatter: (val: number) => `${val}%`,
|
||||
},
|
||||
};
|
||||
|
||||
const chartSeries = [35, 28, 22, 15];
|
||||
|
||||
return (
|
||||
<>
|
||||
<PageMeta title="Thinker Dashboard - IGNY8" description="AI thinker overview" />
|
||||
|
||||
<ComponentCard title="Coming Soon" desc="AI thinker overview">
|
||||
<div className="text-center py-8">
|
||||
<p className="text-gray-600 dark:text-gray-400">
|
||||
Thinker Dashboard - Coming Soon
|
||||
</p>
|
||||
<p className="text-sm text-gray-500 dark:text-gray-400 mt-2">
|
||||
Overview of AI tools and strategies will be displayed here
|
||||
</p>
|
||||
<PageMeta title="Thinker Dashboard - IGNY8" description="Strategic OS and thinking engine" />
|
||||
<PageHeader title="Thinker Dashboard" />
|
||||
|
||||
<div className="space-y-6">
|
||||
{/* Key Metrics */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
|
||||
<EnhancedMetricCard
|
||||
title="Prompt Library"
|
||||
value={stats?.totalPrompts || 0}
|
||||
icon={DocumentTextIcon}
|
||||
trend={{ value: 0, isPositive: true }}
|
||||
color="from-[#ff7a00] to-[#cc5f00]"
|
||||
loading={loading}
|
||||
/>
|
||||
<EnhancedMetricCard
|
||||
title="Author Profiles"
|
||||
value={stats?.activeProfiles || 0}
|
||||
icon={UserIcon}
|
||||
trend={{ value: 0, isPositive: true }}
|
||||
color="from-[#0693e3] to-[#0472b8]"
|
||||
loading={loading}
|
||||
/>
|
||||
<EnhancedMetricCard
|
||||
title="Strategies"
|
||||
value={stats?.strategies || 0}
|
||||
icon={ShootingStarIcon}
|
||||
trend={{ value: 0, isPositive: true }}
|
||||
color="from-[#5d4ae3] to-[#3a2f94]"
|
||||
loading={loading}
|
||||
/>
|
||||
<EnhancedMetricCard
|
||||
title="Usage This Month"
|
||||
value={stats?.usageThisMonth || 0}
|
||||
icon={BoltIcon}
|
||||
trend={{ value: 0, isPositive: true }}
|
||||
color="from-[#0bbf87] to-[#08966b]"
|
||||
loading={loading}
|
||||
/>
|
||||
</div>
|
||||
</ComponentCard>
|
||||
|
||||
{/* Thinker Modules */}
|
||||
<ComponentCard title="Thinker Modules" desc="Manage prompts, profiles, and strategies">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
|
||||
{thinkerModules.map((module) => {
|
||||
const Icon = module.icon;
|
||||
return (
|
||||
<Link
|
||||
key={module.title}
|
||||
to={module.path}
|
||||
className="rounded-2xl border-2 border-slate-200 bg-white p-6 hover:shadow-xl hover:-translate-y-1 transition-all group"
|
||||
>
|
||||
<div className="flex items-start justify-between mb-4">
|
||||
<div className={`inline-flex size-14 rounded-xl bg-gradient-to-br ${module.color} items-center justify-center text-white shadow-lg`}>
|
||||
<Icon className="h-7 w-7" />
|
||||
</div>
|
||||
{module.status === "coming-soon" && (
|
||||
<span className="inline-flex items-center px-2 py-1 rounded-full text-xs font-semibold bg-slate-100 text-slate-600">
|
||||
Soon
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<h3 className="text-lg font-bold text-slate-900 mb-2">{module.title}</h3>
|
||||
<p className="text-sm text-slate-600 mb-4">{module.description}</p>
|
||||
{module.count > 0 && (
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-2xl font-bold text-slate-900">{module.count}</span>
|
||||
<ArrowRightIcon className="h-5 w-5 text-slate-400 group-hover:text-[#0693e3] group-hover:translate-x-1 transition" />
|
||||
</div>
|
||||
)}
|
||||
{module.status === "coming-soon" && (
|
||||
<div className="mt-4 pt-4 border-t border-slate-200">
|
||||
<span className="text-xs text-slate-500">Coming soon</span>
|
||||
</div>
|
||||
)}
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</ComponentCard>
|
||||
|
||||
{/* Recent Activity & Usage Chart */}
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
||||
<ComponentCard title="Prompt Usage Distribution" desc="How your prompts are being used">
|
||||
<Suspense fallback={<div className="h-[300px] flex items-center justify-center">Loading chart...</div>}>
|
||||
<Chart options={chartOptions} series={chartSeries} type="donut" height={300} />
|
||||
</Suspense>
|
||||
</ComponentCard>
|
||||
|
||||
<ComponentCard title="Most Used Prompts" desc="Your top-performing prompt templates">
|
||||
<div className="space-y-4">
|
||||
{recentPrompts.map((prompt) => (
|
||||
<div
|
||||
key={prompt.id}
|
||||
className="flex items-center gap-4 p-4 rounded-lg border border-slate-200 bg-white hover:shadow-md transition"
|
||||
>
|
||||
<div className="size-10 rounded-lg bg-gradient-to-br from-[#ff7a00] to-[#cc5f00] flex items-center justify-center text-white shadow-md">
|
||||
<DocumentTextIcon className="h-5 w-5" />
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<div className="flex items-center justify-between mb-1">
|
||||
<h4 className="font-semibold text-slate-900">{prompt.name}</h4>
|
||||
<span className="text-xs font-semibold text-[#0693e3]">{prompt.usage} uses</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-3 text-xs text-slate-600">
|
||||
<span>{prompt.category}</span>
|
||||
<span>•</span>
|
||||
<span>{prompt.lastUsed}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</ComponentCard>
|
||||
</div>
|
||||
|
||||
{/* Quick Actions */}
|
||||
<ComponentCard title="Quick Actions" desc="Create new prompts, profiles, or strategies">
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||||
<button
|
||||
onClick={() => navigate("/thinker/prompts")}
|
||||
className="flex items-center gap-4 p-6 rounded-xl border-2 border-slate-200 bg-white hover:border-[#ff7a00] hover:shadow-lg transition-all group"
|
||||
>
|
||||
<div className="size-12 rounded-xl bg-gradient-to-br from-[#ff7a00] to-[#cc5f00] flex items-center justify-center text-white shadow-lg">
|
||||
<PlusIcon className="h-6 w-6" />
|
||||
</div>
|
||||
<div className="flex-1 text-left">
|
||||
<h4 className="font-semibold text-slate-900 mb-1">New Prompt</h4>
|
||||
<p className="text-sm text-slate-600">Create a reusable prompt template</p>
|
||||
</div>
|
||||
<ArrowRightIcon className="h-5 w-5 text-slate-400 group-hover:text-[#ff7a00] transition" />
|
||||
</button>
|
||||
|
||||
<button
|
||||
onClick={() => navigate("/thinker/profiles")}
|
||||
className="flex items-center gap-4 p-6 rounded-xl border-2 border-slate-200 bg-white hover:border-[#0693e3] hover:shadow-lg transition-all group"
|
||||
>
|
||||
<div className="size-12 rounded-xl bg-gradient-to-br from-[#0693e3] to-[#0472b8] flex items-center justify-center text-white shadow-lg">
|
||||
<PlusIcon className="h-6 w-6" />
|
||||
</div>
|
||||
<div className="flex-1 text-left">
|
||||
<h4 className="font-semibold text-slate-900 mb-1">New Author Profile</h4>
|
||||
<p className="text-sm text-slate-600">Define a writing voice and style</p>
|
||||
</div>
|
||||
<ArrowRightIcon className="h-5 w-5 text-slate-400 group-hover:text-[#0693e3] transition" />
|
||||
</button>
|
||||
|
||||
<button
|
||||
onClick={() => navigate("/thinker/strategies")}
|
||||
className="flex items-center gap-4 p-6 rounded-xl border-2 border-slate-200 bg-white hover:border-[#5d4ae3] hover:shadow-lg transition-all group"
|
||||
>
|
||||
<div className="size-12 rounded-xl bg-gradient-to-br from-[#5d4ae3] to-[#3a2f94] flex items-center justify-center text-white shadow-lg">
|
||||
<PlusIcon className="h-6 w-6" />
|
||||
</div>
|
||||
<div className="flex-1 text-left">
|
||||
<h4 className="font-semibold text-slate-900 mb-1">New Strategy</h4>
|
||||
<p className="text-sm text-slate-600">Build a content playbook</p>
|
||||
</div>
|
||||
<ArrowRightIcon className="h-5 w-5 text-slate-400 group-hover:text-[#5d4ae3] transition" />
|
||||
</button>
|
||||
</div>
|
||||
</ComponentCard>
|
||||
|
||||
{/* Info Cards */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<ComponentCard title="How Thinker Works" desc="Understanding the strategic OS">
|
||||
<div className="space-y-4">
|
||||
<div className="flex gap-4">
|
||||
<div className="flex-shrink-0 size-10 rounded-lg bg-gradient-to-br from-[#ff7a00] to-[#cc5f00] flex items-center justify-center text-white shadow-md">
|
||||
<BoltIcon className="h-5 w-5" />
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="font-semibold text-slate-900 mb-1">Centralized Control</h4>
|
||||
<p className="text-sm text-slate-600">
|
||||
Manage all AI prompts, author voices, and brand guidelines in one place. Changes sync automatically to all content generation.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex gap-4">
|
||||
<div className="flex-shrink-0 size-10 rounded-lg bg-gradient-to-br from-[#0693e3] to-[#0472b8] flex items-center justify-center text-white shadow-md">
|
||||
<CheckCircleIcon className="h-5 w-5" />
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="font-semibold text-slate-900 mb-1">Version Control</h4>
|
||||
<p className="text-sm text-slate-600">
|
||||
Track changes to prompts and strategies with full version history. Roll back to previous versions when needed.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex gap-4">
|
||||
<div className="flex-shrink-0 size-10 rounded-lg bg-gradient-to-br from-[#0bbf87] to-[#08966b] flex items-center justify-center text-white shadow-md">
|
||||
<ShootingStarIcon className="h-5 w-5" />
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="font-semibold text-slate-900 mb-1">Automated Enforcement</h4>
|
||||
<p className="text-sm text-slate-600">
|
||||
Every piece of content automatically uses your defined prompts, author profiles, and brand guidelines.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ComponentCard>
|
||||
|
||||
<ComponentCard title="Getting Started" desc="Quick guide to using Thinker">
|
||||
<div className="space-y-3">
|
||||
<div className="flex items-start gap-3">
|
||||
<div className="flex-shrink-0 size-8 rounded-full bg-[#0693e3] text-white flex items-center justify-center font-bold text-sm">
|
||||
1
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="font-semibold text-slate-900 mb-1">Create Author Profiles</h4>
|
||||
<p className="text-sm text-slate-600">
|
||||
Define writing voices and styles that match your brand. Each profile can have unique tone, structure, and guidelines.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-start gap-3">
|
||||
<div className="flex-shrink-0 size-8 rounded-full bg-[#0bbf87] text-white flex items-center justify-center font-bold text-sm">
|
||||
2
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="font-semibold text-slate-900 mb-1">Build Prompt Library</h4>
|
||||
<p className="text-sm text-slate-600">
|
||||
Create reusable prompt templates for different content types. Use variables to make prompts dynamic and flexible.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-start gap-3">
|
||||
<div className="flex-shrink-0 size-8 rounded-full bg-[#5d4ae3] text-white flex items-center justify-center font-bold text-sm">
|
||||
3
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="font-semibold text-slate-900 mb-1">Define Strategies</h4>
|
||||
<p className="text-sm text-slate-600">
|
||||
Create content playbooks that combine prompts, profiles, and guidelines. Apply strategies to specific clusters or content types.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ComponentCard>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user