diff --git a/frontend/src/components/admin/content/AvatarManager.tsx b/frontend/src/components/admin/content/AvatarManager.tsx index bba91f0..87bd5ed 100644 --- a/frontend/src/components/admin/content/AvatarManager.tsx +++ b/frontend/src/components/admin/content/AvatarManager.tsx @@ -4,52 +4,20 @@ import { getDirectusClient } from '@/lib/directus/client'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Badge } from '@/components/ui/badge'; -export default function AvatarManager() { - const [avatars, setAvatars] = useState([]); - const [variants, setVariants] = useState([]); - const [loading, setLoading] = useState(true); +interface Props { + initialAvatars?: any[]; + initialVariants?: any[]; +} + +export default function AvatarManager({ initialAvatars = [], initialVariants = [] }: Props) { + const [avatars, setAvatars] = useState(initialAvatars); + const [variants, setVariants] = useState(initialVariants); const [selectedAvatar, setSelectedAvatar] = useState(null); - useEffect(() => { - loadData(); - }, []); - - const loadData = async () => { - try { - const directus = await getDirectusClient(); - - // Load avatars - const avatarData = await directus.request({ - method: 'GET', - path: '/items/avatar_intelligence' - }); - setAvatars(avatarData.data || []); - - // Load variants - const variantData = await directus.request({ - method: 'GET', - path: '/items/avatar_variants' - }); - setVariants(variantData.data || []); - - setLoading(false); - } catch (error) { - console.error('Error loading avatars:', error); - setLoading(false); - } - }; - const getVariantsForAvatar = (avatarKey) => { return variants.filter(v => v.avatar_key === avatarKey); }; - if (loading) { - return ( -
-
Loading avatars...
-
- ); - } return (
diff --git a/frontend/src/components/admin/content/CartesianManager.tsx b/frontend/src/components/admin/content/CartesianManager.tsx index 62143ea..ed83e30 100644 --- a/frontend/src/components/admin/content/CartesianManager.tsx +++ b/frontend/src/components/admin/content/CartesianManager.tsx @@ -4,32 +4,12 @@ import { getDirectusClient } from '@/lib/directus/client'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Badge } from '@/components/ui/badge'; -export default function CartesianManager() { - const [patterns, setPatterns] = useState([]); - const [loading, setLoading] = useState(true); +interface Props { + initialPatterns?: any[]; +} - useEffect(() => { - loadData(); - }, []); - - const loadData = async () => { - try { - const directus = await getDirectusClient(); - const response = await directus.request({ - method: 'GET', - path: '/items/cartesian_patterns' - }); - setPatterns(response.data || []); - setLoading(false); - } catch (error) { - console.error('Error loading cartesian patterns:', error); - setLoading(false); - } - }; - - if (loading) { - return
Loading Cartesian Patterns...
; - } +export default function CartesianManager({ initialPatterns = [] }: Props) { + const [patterns, setPatterns] = useState(initialPatterns); return (
diff --git a/frontend/src/components/admin/content/GeoManager.tsx b/frontend/src/components/admin/content/GeoManager.tsx index 25e3f35..7a739fa 100644 --- a/frontend/src/components/admin/content/GeoManager.tsx +++ b/frontend/src/components/admin/content/GeoManager.tsx @@ -4,32 +4,12 @@ import { getDirectusClient } from '@/lib/directus/client'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Badge } from '@/components/ui/badge'; -export default function GeoManager() { - const [clusters, setClusters] = useState([]); - const [loading, setLoading] = useState(true); +interface Props { + initialClusters?: any[]; +} - useEffect(() => { - loadData(); - }, []); - - const loadData = async () => { - try { - const directus = await getDirectusClient(); - const response = await directus.request({ - method: 'GET', - path: '/items/geo_intelligence' - }); - setClusters(response.data || []); - setLoading(false); - } catch (error) { - console.error('Error loading geo clusters:', error); - setLoading(false); - } - }; - - if (loading) { - return
Loading Geo Intelligence...
; - } +export default function GeoManager({ initialClusters = [] }: Props) { + const [clusters, setClusters] = useState(initialClusters); return (
diff --git a/frontend/src/components/admin/content/SpintaxManager.tsx b/frontend/src/components/admin/content/SpintaxManager.tsx index d144f08..10cd425 100644 --- a/frontend/src/components/admin/content/SpintaxManager.tsx +++ b/frontend/src/components/admin/content/SpintaxManager.tsx @@ -4,32 +4,12 @@ import { getDirectusClient } from '@/lib/directus/client'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Badge } from '@/components/ui/badge'; -export default function SpintaxManager() { - const [dictionaries, setDictionaries] = useState([]); - const [loading, setLoading] = useState(true); +interface Props { + initialDictionaries?: any[]; +} - useEffect(() => { - loadData(); - }, []); - - const loadData = async () => { - try { - const directus = await getDirectusClient(); - const response = await directus.request({ - method: 'GET', - path: '/items/spintax_dictionaries' - }); - setDictionaries(response.data || []); - setLoading(false); - } catch (error) { - console.error('Error loading spintax dictionaries:', error); - setLoading(false); - } - }; - - if (loading) { - return
Loading Spintax Dictionaries...
; - } +export default function SpintaxManager({ initialDictionaries = [] }: Props) { + const [dictionaries, setDictionaries] = useState(initialDictionaries); return (
diff --git a/frontend/src/pages/admin/content/avatars.astro b/frontend/src/pages/admin/content/avatars.astro index 12122fe..d161b0a 100644 --- a/frontend/src/pages/admin/content/avatars.astro +++ b/frontend/src/pages/admin/content/avatars.astro @@ -2,6 +2,11 @@ --- import Layout from '@/layouts/AdminLayout.astro'; import AvatarManager from '@/components/admin/content/AvatarManager'; +import { getDirectusClient, readItems } from '@/lib/directus/client'; + +const directus = getDirectusClient(); +const avatars = await directus.request(readItems('avatar_intelligence')).catch(() => []); +const variants = await directus.request(readItems('avatar_variants')).catch(() => []); ---
@@ -9,6 +14,6 @@ import AvatarManager from '@/components/admin/content/AvatarManager';

Avatar Intelligence

Manage your 10 base avatars, variants, and business niches.

- +
diff --git a/frontend/src/pages/admin/content/cartesian_patterns.astro b/frontend/src/pages/admin/content/cartesian_patterns.astro index 301c5b6..8752f1b 100644 --- a/frontend/src/pages/admin/content/cartesian_patterns.astro +++ b/frontend/src/pages/admin/content/cartesian_patterns.astro @@ -1,14 +1,17 @@ - --- import Layout from '@/layouts/AdminLayout.astro'; import CartesianManager from '@/components/admin/content/CartesianManager'; +import { getDirectusClient, readItems } from '@/lib/directus/client'; + +const directus = getDirectusClient(); +const patterns = await directus.request(readItems('cartesian_patterns')).catch(() => []); ---

Cartesian Patterns

-

Headline and Hook Formulas for the Multiplication Engine.

+

Manage headline and content generation formulas.

- +
diff --git a/frontend/src/pages/admin/content/geo_clusters.astro b/frontend/src/pages/admin/content/geo_clusters.astro index f749184..b46a359 100644 --- a/frontend/src/pages/admin/content/geo_clusters.astro +++ b/frontend/src/pages/admin/content/geo_clusters.astro @@ -1,14 +1,17 @@ - --- import Layout from '@/layouts/AdminLayout.astro'; import GeoManager from '@/components/admin/content/GeoManager'; +import { getDirectusClient, readItems } from '@/lib/directus/client'; + +const directus = getDirectusClient(); +const clusters = await directus.request(readItems('geo_intelligence')).catch(() => []); --- - +
-

Geo Clusters

-

Manage Geographic Intelligence (Silicon Valleys, Growth Havens) for localized content.

+

Geo Intelligence

+

Manage your geographic targeting clusters.

- +
diff --git a/frontend/src/pages/admin/content/spintax_dictionaries.astro b/frontend/src/pages/admin/content/spintax_dictionaries.astro index 7275b6c..ec2e4a3 100644 --- a/frontend/src/pages/admin/content/spintax_dictionaries.astro +++ b/frontend/src/pages/admin/content/spintax_dictionaries.astro @@ -1,14 +1,17 @@ - --- import Layout from '@/layouts/AdminLayout.astro'; import SpintaxManager from '@/components/admin/content/SpintaxManager'; +import { getDirectusClient, readItems } from '@/lib/directus/client'; + +const directus = getDirectusClient(); +const dictionaries = await directus.request(readItems('spintax_dictionaries')).catch(() => []); --- - +

Spintax Dictionaries

-

Global Search & Replace Dictionaries for content randomization.

+

Manage word variations for automated content generation.

- +
diff --git a/full-schema-update.sql b/full-schema-update.sql new file mode 100644 index 0000000..927a823 --- /dev/null +++ b/full-schema-update.sql @@ -0,0 +1,137 @@ +-- Spark Platform - Full Schema Update +-- Adds missing tables for SEO Engine and Cartesian Engine + +-- 1. generated_articles (replacing/aliasing posts) +CREATE TABLE IF NOT EXISTS generated_articles ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid (), + site_id UUID REFERENCES sites (id) ON DELETE CASCADE, + title VARCHAR(500) NOT NULL, + slug VARCHAR(500) NOT NULL, + html_content TEXT, + generation_hash VARCHAR(255), + meta_desc TEXT, + is_published BOOLEAN DEFAULT FALSE, + sync_status VARCHAR(50), + sitemap_status VARCHAR(50) DEFAULT 'ghost', -- ghost, queued, indexed + campaign_id UUID, -- Reference to campaign_masters + date_created TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + date_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); + +-- 2. campaign_masters +CREATE TABLE IF NOT EXISTS campaign_masters ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid (), + site_id UUID REFERENCES sites (id) ON DELETE CASCADE, + name VARCHAR(255) NOT NULL, + headline_spintax_root TEXT, + niche_variables JSONB, + location_mode VARCHAR(50), + location_target VARCHAR(255), + batch_count INTEGER DEFAULT 0, + status VARCHAR(50) DEFAULT 'active', + date_created TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); + +-- 3. headline_inventory +CREATE TABLE IF NOT EXISTS headline_inventory ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid (), + campaign_id UUID REFERENCES campaign_masters (id) ON DELETE CASCADE, + final_title_text TEXT NOT NULL, + status VARCHAR(50) DEFAULT 'available', + used_on_article UUID, -- Reference to generated_articles + date_created TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); + +-- 4. content_fragments +CREATE TABLE IF NOT EXISTS content_fragments ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid (), + campaign_id UUID REFERENCES campaign_masters (id) ON DELETE CASCADE, + fragment_type VARCHAR(100), + content_body TEXT, + word_count INTEGER, + date_created TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); + +-- 5. generation_jobs (Cartesian Engine) +CREATE TABLE IF NOT EXISTS generation_jobs ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid (), + site_id UUID REFERENCES sites (id) ON DELETE CASCADE, + target_quantity INTEGER, + status VARCHAR(50) DEFAULT 'Pending', + filters JSONB, + current_offset INTEGER DEFAULT 0, + date_created TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); + +-- Register collections +INSERT INTO + directus_collections ( + collection, + icon, + note, + hidden, + singleton, + accountability + ) +VALUES ( + 'generated_articles', + 'article', + 'SEO Generated Articles', + false, + false, + 'all' + ), + ( + 'campaign_masters', + 'campaign', + 'SEO Campaigns', + false, + false, + 'all' + ), + ( + 'headline_inventory', + 'title', + 'Generated Headlines', + false, + false, + 'all' + ), + ( + 'content_fragments', + 'extension', + 'Content Blocks', + false, + false, + 'all' + ), + ( + 'generation_jobs', + 'engineering', + 'Generation Jobs', + false, + false, + 'all' + ) ON CONFLICT (collection) DO NOTHING; + +-- Register fields for generated_articles +INSERT INTO directus_fields (collection, field, type, interface, special) +VALUES + ('generated_articles', 'id', 'uuid', 'input', ARRAY['uuid']), + ('generated_articles', 'site_id', 'uuid', 'select-dropdown-m2o', NULL), + ('generated_articles', 'title', 'string', 'input', NULL), + ('generated_articles', 'slug', 'string', 'input', NULL), + ('generated_articles', 'html_content', 'text', 'input-rich-text-html', NULL), + ('generated_articles', 'is_published', 'boolean', 'boolean', NULL), + ('generated_articles', 'sitemap_status', 'string', 'select-dropdown', NULL), + ('generated_articles', 'date_created', 'timestamp', 'datetime', ARRAY['date-created']) +ON CONFLICT (collection, field) DO NOTHING; + +-- Register fields for campaign_masters +INSERT INTO directus_fields (collection, field, type, interface, special) +VALUES + ('campaign_masters', 'id', 'uuid', 'input', ARRAY['uuid']), + ('campaign_masters', 'name', 'string', 'input', NULL), + ('campaign_masters', 'status', 'string', 'select-dropdown', NULL), + ('campaign_masters', 'date_created', 'timestamp', 'datetime', ARRAY['date-created']) +ON CONFLICT (collection, field) DO NOTHING; \ No newline at end of file