feat: Completed Milestone 1 - Full Intelligence Library Suite

- Implemented Cartesian Manager with live Formula Builder
- Added Dynamic Preview to Cartesian Manager (fetches real Geo/Spintax data)
- Completed Spintax Manager with Schema Mapping
- Updated Roadmap to reflect 100% Milestone 1 completion
- Fixed all pending lint errors & type mismatches
This commit is contained in:
cawcenter
2025-12-13 20:16:59 -05:00
parent 97d5b4a58c
commit 5aaef362b4
4 changed files with 411 additions and 170 deletions

View File

@@ -1,161 +1,20 @@
---
/**
* Cartesian Patterns Management
* Content structure templates and formulas
*/
import AdminLayout from '@/layouts/AdminLayout.astro';
import { getDirectusClient } from '@/lib/directus/client';
import { readItems } from '@directus/sdk';
const client = getDirectusClient();
let patterns = [];
let error = null;
let stats = {
total: 0,
byType: {} as Record<string, number>,
};
try {
patterns = await client.request(readItems('cartesian_patterns', {
fields: ['*'],
sort: ['structure_type', 'pattern_name'],
}));
stats.total = patterns.length;
patterns.forEach((p: any) => {
const type = p.structure_type || 'general';
stats.byType[type] = (stats.byType[type] || 0) + 1;
});
} catch (e) {
console.error('Error fetching patterns:', e);
error = e instanceof Error ? e.message : 'Unknown error';
}
import Layout from '@/layouts/AdminLayout.astro';
import CartesianManager from '@/components/admin/intelligence/CartesianManager';
---
<AdminLayout title="Cartesian Patterns">
<div class="space-y-6">
<!-- Header -->
<div class="flex justify-between items-center">
<Layout title="Cartesian Patterns | Spark Intelligence">
<div class="p-8 space-y-6">
<div class="flex justify-between items-start">
<div>
<h1 class="spark-heading text-3xl">🔧 Cartesian Patterns</h1>
<p class="text-silver mt-1">Content structure templates and formulas</p>
</div>
<div class="flex gap-3">
<button class="spark-btn-secondary text-sm" onclick="window.dispatchEvent(new CustomEvent('import-modal'))">
📥 Import
</button>
<button class="spark-btn-secondary text-sm" onclick="window.dispatchEvent(new CustomEvent('export-data', {detail: {collection: 'cartesian_patterns'}}))">
📤 Export
</button>
<a href="/admin/collections/cartesian-patterns/new" class="spark-btn-primary text-sm">
✨ New Pattern
</a>
<h1 class="text-3xl font-bold text-white tracking-tight">📐 Cartesian Patterns</h1>
<p class="text-zinc-400 mt-2 max-w-2xl">
Create logic-based sentence formulas. Combine text, spintax, and variables like
<code>&#123;city&#125;</code> or <code>&#123;service&#125;</code> to generate millions of unique combinations.
</p>
</div>
</div>
{error && (
<div class="spark-card p-4 border-red-500 text-red-400">
<strong>Error:</strong> {error}
</div>
)}
<!-- Stats -->
<div class="grid grid-cols-2 md:grid-cols-4 gap-4">
<div class="spark-card p-6">
<div class="spark-label mb-2">Total Patterns</div>
<div class="spark-data text-3xl">{stats.total}</div>
</div>
{Object.entries(stats.byType).slice(0, 3).map(([type, count]) => (
<div class="spark-card p-6">
<div class="spark-label mb-2 capitalize">{type}</div>
<div class="spark-data text-3xl text-gold">{count}</div>
</div>
))}
</div>
<!-- Patterns List -->
<div class="space-y-4">
{patterns.map((pattern: any) => (
<div class="spark-card spark-card-hover p-6">
<div class="flex items-start justify-between gap-4 mb-4">
<div>
<h3 class="text-white font-semibold text-lg">{pattern.pattern_name || 'Unnamed Pattern'}</h3>
{pattern.description && (
<p class="text-silver/70 text-sm mt-1">{pattern.description}</p>
)}
</div>
<span class="px-3 py-1 bg-gold/10 text-gold text-xs rounded border border-gold/30">
{pattern.structure_type || 'general'}
</span>
</div>
{pattern.template && (
<div class="mb-4 p-4 bg-black/30 rounded border border-edge-subtle font-mono">
<div class="spark-label mb-2">Template:</div>
<div class="text-sm text-green-400 whitespace-pre-wrap">
{pattern.template}
</div>
</div>
)}
{pattern.variables && Array.isArray(pattern.variables) && (
<div class="mb-4">
<div class="spark-label mb-2">Variables:</div>
<div class="flex flex-wrap gap-2">
{pattern.variables.map((variable: string) => (
<span class="px-3 py-1 bg-blue-500/10 text-blue-400 text-xs rounded border border-blue-500/20 font-mono">
{'{{'}{variable}{'}}'}
</span>
))}
</div>
</div>
)}
{pattern.example_output && (
<div class="p-4 bg-graphite rounded border border-edge-subtle">
<div class="spark-label mb-2">Example Output:</div>
<div class="text-silver text-sm italic">
"{pattern.example_output}"
</div>
</div>
)}
<div class="flex gap-2 mt-4">
<button
class="spark-btn-ghost text-xs px-3 py-1"
onclick={`navigator.clipboard.writeText(${JSON.stringify(pattern.template || '')})`}
>
📋 Copy Template
</button>
<a href={`/admin/collections/cartesian-patterns/${pattern.id}`} class="spark-btn-ghost text-xs px-3 py-1">
Edit
</a>
<button class="spark-btn-secondary text-xs px-3 py-1">
🧪 Test Pattern
</button>
</div>
</div>
))}
{patterns.length === 0 && !error && (
<div class="spark-card p-12 text-center">
<p class="text-silver/50">No patterns found. Create your first content template!</p>
</div>
)}
</div>
<CartesianManager client:only="react" />
</div>
</AdminLayout>
<script>
window.addEventListener('export-data', async (e: any) => {
const { collection } = e.detail;
const response = await fetch(`/api/collections/${collection}/export`);
const blob = await response.blob();
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `${collection}-${new Date().toISOString().split('T')[0]}.json`;
a.click();
});
</script>
</Layout>