## Responsive Admin UI - Layout.tsx: Mobile sidebar drawer with hamburger menu - Dashboard.tsx: 2-col grid on mobile, responsive stats cards - OrchestratorDashboard.tsx: Responsive table with hidden columns - PagesTab.tsx: Responsive filters and table ## SEO Pages - New /admin/seo section with state landing pages - SEO page generation and management - State page content with dispensary/product counts ## Click Analytics - Product click tracking infrastructure - Click analytics dashboard ## Other Changes - Consumer features scaffolding (alerts, deals, favorites) - Health panel component - Workers dashboard improvements - Legacy DutchieAZ pages removed 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
23 lines
1.1 KiB
SQL
23 lines
1.1 KiB
SQL
-- SEO Pages table for CannaiQ marketing content
|
|
-- All content stored here must be sanitized before insertion
|
|
|
|
CREATE TABLE IF NOT EXISTS seo_pages (
|
|
id SERIAL PRIMARY KEY,
|
|
slug VARCHAR(255) NOT NULL UNIQUE,
|
|
type VARCHAR(50) NOT NULL, -- state, brand, competitor, landing, blog
|
|
content JSONB NOT NULL,
|
|
status VARCHAR(20) NOT NULL DEFAULT 'draft', -- draft, published, archived
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
|
);
|
|
|
|
-- Indexes for efficient lookup
|
|
CREATE INDEX IF NOT EXISTS idx_seo_pages_slug ON seo_pages(slug);
|
|
CREATE INDEX IF NOT EXISTS idx_seo_pages_type ON seo_pages(type);
|
|
CREATE INDEX IF NOT EXISTS idx_seo_pages_status ON seo_pages(status);
|
|
CREATE INDEX IF NOT EXISTS idx_seo_pages_type_status ON seo_pages(type, status);
|
|
|
|
-- Add comment explaining content requirements
|
|
COMMENT ON TABLE seo_pages IS 'SEO content for CannaiQ marketing pages. All content must use approved enterprise-safe phrasing.';
|
|
COMMENT ON COLUMN seo_pages.content IS 'JSON content with blocks structure. Must be sanitized via ContentValidator before insert.';
|