398 lines
16 KiB
TypeScript
398 lines
16 KiB
TypeScript
import { useEffect, useState, lazy, Suspense } from "react";
|
|
import { Link, useNavigate } from "react-router-dom";
|
|
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-[var(--color-warning)] to-[var(--color-warning-dark)]",
|
|
path: "/thinker/prompts",
|
|
count: stats?.totalPrompts || 0,
|
|
status: "active",
|
|
},
|
|
{
|
|
title: "Author Profiles",
|
|
description: "Voice templates and writing style guides",
|
|
icon: UserIcon,
|
|
color: "from-[var(--color-primary)] to-[var(--color-primary-dark)]",
|
|
path: "/thinker/profiles",
|
|
count: stats?.activeProfiles || 0,
|
|
status: "active",
|
|
},
|
|
{
|
|
title: "Content Strategies",
|
|
description: "Brand playbooks and content frameworks",
|
|
icon: ShootingStarIcon,
|
|
color: "from-[var(--color-purple)] to-[var(--color-purple-dark)]",
|
|
path: "/thinker/strategies",
|
|
count: stats?.strategies || 0,
|
|
status: "active",
|
|
},
|
|
{
|
|
title: "Governance",
|
|
description: "Track AI usage, compliance, and version control",
|
|
icon: PieChartIcon,
|
|
color: "from-[var(--color-success)] to-[var(--color-success-dark)]",
|
|
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: ["var(--color-warning)", "var(--color-primary)", "var(--color-purple)", "var(--color-success)"],
|
|
legend: {
|
|
position: "bottom",
|
|
labels: { colors: "var(--color-gray-500)" },
|
|
},
|
|
dataLabels: {
|
|
enabled: true,
|
|
formatter: (val: number) => `${val}%`,
|
|
},
|
|
};
|
|
|
|
const chartSeries = [35, 28, 22, 15];
|
|
|
|
return (
|
|
<>
|
|
<PageMeta title="Strategy Dashboard - IGNY8" description="Manage your content strategy" />
|
|
<PageHeader title="Strategy 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={<FileTextIcon className="size-6" />}
|
|
trend={0}
|
|
accentColor="orange"
|
|
/>
|
|
<EnhancedMetricCard
|
|
title="Author Profiles"
|
|
value={stats?.activeProfiles || 0}
|
|
icon={<UserIcon className="size-6" />}
|
|
trend={0}
|
|
accentColor="blue"
|
|
/>
|
|
<EnhancedMetricCard
|
|
title="Strategies"
|
|
value={stats?.strategies || 0}
|
|
icon={<ShootingStarIcon className="size-6" />}
|
|
trend={0}
|
|
accentColor="purple"
|
|
/>
|
|
<EnhancedMetricCard
|
|
title="Usage This Month"
|
|
value={stats?.usageThisMonth || 0}
|
|
icon={<BoltIcon className="size-6" />}
|
|
trend={0}
|
|
accentColor="green"
|
|
/>
|
|
</div>
|
|
|
|
{/* 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-gray-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-gray-100 text-gray-600">
|
|
Soon
|
|
</span>
|
|
)}
|
|
</div>
|
|
<h3 className="text-lg font-bold text-gray-900 mb-2">{module.title}</h3>
|
|
<p className="text-sm text-gray-600 mb-4">{module.description}</p>
|
|
{module.count > 0 && (
|
|
<div className="flex items-center justify-between">
|
|
<span className="text-2xl font-bold text-gray-900">{module.count}</span>
|
|
<ArrowRightIcon className="h-5 w-5 text-gray-400 group-hover:text-[var(--color-primary)] group-hover:translate-x-1 transition" />
|
|
</div>
|
|
)}
|
|
{module.status === "coming-soon" && (
|
|
<div className="mt-4 pt-4 border-t border-gray-200">
|
|
<span className="text-xs text-gray-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-gray-200 bg-white hover:shadow-md transition"
|
|
>
|
|
<div className="size-10 rounded-lg bg-gradient-to-br from-[var(--color-warning)] to-[var(--color-warning-dark)] flex items-center justify-center text-white shadow-md">
|
|
<FileTextIcon className="h-5 w-5" />
|
|
</div>
|
|
<div className="flex-1">
|
|
<div className="flex items-center justify-between mb-1">
|
|
<h4 className="font-semibold text-gray-900">{prompt.name}</h4>
|
|
<span className="text-xs font-semibold text-[var(--color-primary)]">{prompt.usage} uses</span>
|
|
</div>
|
|
<div className="flex items-center gap-3 text-xs text-gray-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")}
|
|
variant="outline"
|
|
size="lg"
|
|
startIcon={
|
|
<div className="size-8 rounded-lg bg-gradient-to-br from-[var(--color-warning)] to-[var(--color-warning-dark)] flex items-center justify-center text-white shadow-md">
|
|
<PlusIcon className="h-4 w-4" />
|
|
</div>
|
|
}
|
|
className="!justify-start !h-auto !py-4"
|
|
>
|
|
<div className="flex-1 text-left">
|
|
<h4 className="font-semibold text-gray-900 mb-1">New Prompt</h4>
|
|
<p className="text-sm text-gray-600">Create a reusable prompt template</p>
|
|
</div>
|
|
</Button>
|
|
|
|
<Button
|
|
onClick={() => navigate("/thinker/profiles")}
|
|
variant="outline"
|
|
size="lg"
|
|
startIcon={
|
|
<div className="size-8 rounded-lg bg-gradient-to-br from-[var(--color-primary)] to-[var(--color-primary-dark)] flex items-center justify-center text-white shadow-md">
|
|
<PlusIcon className="h-4 w-4" />
|
|
</div>
|
|
}
|
|
className="!justify-start !h-auto !py-4"
|
|
>
|
|
<div className="flex-1 text-left">
|
|
<h4 className="font-semibold text-gray-900 mb-1">New Author Profile</h4>
|
|
<p className="text-sm text-gray-600">Define a writing voice and style</p>
|
|
</div>
|
|
</Button>
|
|
|
|
<Button
|
|
onClick={() => navigate("/thinker/strategies")}
|
|
variant="outline"
|
|
size="lg"
|
|
startIcon={
|
|
<div className="size-8 rounded-lg bg-gradient-to-br from-[var(--color-purple)] to-[var(--color-purple-dark)] flex items-center justify-center text-white shadow-md">
|
|
<PlusIcon className="h-4 w-4" />
|
|
</div>
|
|
}
|
|
className="!justify-start !h-auto !py-4"
|
|
>
|
|
<div className="flex-1 text-left">
|
|
<h4 className="font-semibold text-gray-900 mb-1">New Strategy</h4>
|
|
<p className="text-sm text-gray-600">Build a content playbook</p>
|
|
</div>
|
|
</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-[var(--color-warning)] to-[var(--color-warning-dark)] flex items-center justify-center text-white shadow-md">
|
|
<BoltIcon className="h-5 w-5" />
|
|
</div>
|
|
<div>
|
|
<h4 className="font-semibold text-gray-900 mb-1">Centralized Control</h4>
|
|
<p className="text-sm text-gray-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-[var(--color-primary)] to-[var(--color-primary-dark)] flex items-center justify-center text-white shadow-md">
|
|
<CheckCircleIcon className="h-5 w-5" />
|
|
</div>
|
|
<div>
|
|
<h4 className="font-semibold text-gray-900 mb-1">Version Control</h4>
|
|
<p className="text-sm text-gray-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-[var(--color-success)] to-[var(--color-success-dark)] flex items-center justify-center text-white shadow-md">
|
|
<ShootingStarIcon className="h-5 w-5" />
|
|
</div>
|
|
<div>
|
|
<h4 className="font-semibold text-gray-900 mb-1">Automated Enforcement</h4>
|
|
<p className="text-sm text-gray-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-brand-500 text-white flex items-center justify-center font-bold text-sm">
|
|
1
|
|
</div>
|
|
<div>
|
|
<h4 className="font-semibold text-gray-900 mb-1">Create Author Profiles</h4>
|
|
<p className="text-sm text-gray-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-success-500 text-white flex items-center justify-center font-bold text-sm">
|
|
2
|
|
</div>
|
|
<div>
|
|
<h4 className="font-semibold text-gray-900 mb-1">Build Prompt Library</h4>
|
|
<p className="text-sm text-gray-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-purple-500 text-white flex items-center justify-center font-bold text-sm">
|
|
3
|
|
</div>
|
|
<div>
|
|
<h4 className="font-semibold text-gray-900 mb-1">Define Strategies</h4>
|
|
<p className="text-sm text-gray-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>
|
|
</>
|
|
);
|
|
}
|