diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 8a04ebe2..906544c1 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -161,14 +161,8 @@ export default function App() { } /> - {/* Planner Module */} - - - - - - } /> + {/* Planner Module - Redirect dashboard to keywords */} + } /> @@ -191,14 +185,8 @@ export default function App() { } /> - {/* Writer Module */} - - - - - - } /> + {/* Writer Module - Redirect dashboard to content */} + } /> @@ -238,14 +226,8 @@ export default function App() { } /> - {/* Linker Module */} - - - - - - } /> + {/* Linker Module - Redirect dashboard to content */} + } /> @@ -254,14 +236,8 @@ export default function App() { } /> - {/* Optimizer Module */} - - - - - - } /> + {/* Optimizer Module - Redirect dashboard to content */} + } /> @@ -355,14 +331,8 @@ export default function App() { } /> - {/* Other Pages */} - - - - - - } /> + {/* Automation Module - Redirect dashboard to rules */} + } /> diff --git a/frontend/src/components/dashboard/ModuleMetricsFooter.tsx b/frontend/src/components/dashboard/ModuleMetricsFooter.tsx new file mode 100644 index 00000000..4a861d84 --- /dev/null +++ b/frontend/src/components/dashboard/ModuleMetricsFooter.tsx @@ -0,0 +1,85 @@ +/** + * ModuleMetricsFooter - Compact metrics footer for table pages + * Shows module-specific metrics at the bottom of table pages + * Uses standard EnhancedMetricCard and ProgressBar components + * Follows standard app design system and color scheme + */ + +import React from 'react'; +import EnhancedMetricCard, { MetricCardProps } from './EnhancedMetricCard'; +import { ProgressBar } from '../ui/progress'; + +export interface MetricItem { + title: string; + value: string | number; + subtitle?: string; + icon: React.ReactNode; + accentColor: MetricCardProps['accentColor']; + href?: string; + onClick?: () => void; +} + +export interface ProgressMetric { + label: string; + value: number; // 0-100 + color?: 'primary' | 'success' | 'warning' | 'purple'; +} + +interface ModuleMetricsFooterProps { + metrics: MetricItem[]; + progress?: ProgressMetric; + className?: string; +} + +export default function ModuleMetricsFooter({ + metrics, + progress, + className = '' +}: ModuleMetricsFooterProps) { + if (metrics.length === 0 && !progress) return null; + + const progressColors = { + primary: 'bg-[var(--color-primary)]', + success: 'bg-[var(--color-success)]', + warning: 'bg-[var(--color-warning)]', + purple: 'bg-[var(--color-purple)]', + }; + + return ( +
+
+ {/* Metrics Grid */} + {metrics.length > 0 && ( +
2 ? 'lg:grid-cols-3' : 'lg:grid-cols-2'} ${metrics.length > 3 ? 'xl:grid-cols-4' : ''} gap-4`}> + {metrics.map((metric, index) => ( + + ))} +
+ )} + + {/* Progress Bar */} + {progress && ( +
+ +
+ )} +
+
+ ); +} + diff --git a/frontend/src/components/navigation/ModuleNavigationTabs.tsx b/frontend/src/components/navigation/ModuleNavigationTabs.tsx new file mode 100644 index 00000000..d39ffa30 --- /dev/null +++ b/frontend/src/components/navigation/ModuleNavigationTabs.tsx @@ -0,0 +1,66 @@ +/** + * ModuleNavigationTabs - Reusable in-page tab navigation component + * Used across Planner, Writer, Linker, Optimizer, Thinker, Automation, Sites modules + * Follows standard app design system and color scheme + */ + +import React from 'react'; +import { Link, useLocation } from 'react-router'; +import { Tabs, TabList, Tab } from '../ui/tabs/Tabs'; + +export interface NavigationTab { + label: string; + path: string; + icon?: React.ReactNode; +} + +interface ModuleNavigationTabsProps { + tabs: NavigationTab[]; + className?: string; +} + +export default function ModuleNavigationTabs({ tabs, className = '' }: ModuleNavigationTabsProps) { + const location = useLocation(); + + // Find active tab based on current path + const activeTab = tabs.find(tab => { + if (tab.path === location.pathname) return true; + // Handle nested routes (e.g., /planner/keywords/123 should match /planner/keywords) + return location.pathname.startsWith(tab.path + '/'); + }); + + const activeTabId = activeTab?.path || tabs[0]?.path || ''; + + return ( +
+ + {(activeTabId, setActiveTab) => ( + + {tabs.map((tab) => { + const isActive = activeTabId === tab.path || location.pathname.startsWith(tab.path + '/'); + + return ( + setActiveTab(tab.path)} + className="flex-1" + > + + {tab.icon && {tab.icon}} + {tab.label} + + + ); + })} + + )} + +
+ ); +} + diff --git a/frontend/src/layout/AppSidebar.tsx b/frontend/src/layout/AppSidebar.tsx index 5f56bf30..0946aae8 100644 --- a/frontend/src/layout/AppSidebar.tsx +++ b/frontend/src/layout/AppSidebar.tsx @@ -78,132 +78,102 @@ const AppSidebar: React.FC = () => { // Define menu sections with useMemo to prevent recreation on every render // Filter out disabled modules based on module enable settings + // New structure: Dashboard (standalone) → SETUP → WORKFLOW → SETTINGS const menuSections: MenuSection[] = useMemo(() => { - const workflowItems: NavItem[] = [ + // SETUP section items (single items, no dropdowns - submenus shown as in-page navigation) + const setupItems: NavItem[] = [ { - icon: , - name: "Setup", - subItems: [ - { name: "Keywords Opportunities", path: "/planner/keyword-opportunities" }, - ], + icon: , + name: "Industry, Sectors & Keywords", + path: "/setup/industries-sectors-keywords", // Merged page + }, + { + icon: , + name: "Sites", + path: "/sites", // Submenus shown as in-page navigation }, ]; + + // Add Automation if enabled (single item, no dropdown) + if (moduleEnabled('automation')) { + setupItems.push({ + icon: , + name: "Automation", + path: "/automation/rules", // Default to rules, submenus shown as in-page navigation + }); + } + + // Add Thinker if enabled (single item, no dropdown) + if (moduleEnabled('thinker')) { + setupItems.push({ + icon: , + name: "Thinker", + path: "/thinker/prompts", // Default to prompts, submenus shown as in-page navigation + }); + } + + // WORKFLOW section items (single items, no dropdowns - submenus shown as in-page navigation) + const workflowItems: NavItem[] = []; - // Add Planner if enabled + // Add Planner if enabled (single item, no dropdown) if (moduleEnabled('planner')) { workflowItems.push({ icon: , name: "Planner", - subItems: [ - { name: "Dashboard", path: "/planner" }, - { name: "Keywords", path: "/planner/keywords" }, - { name: "Clusters", path: "/planner/clusters" }, - { name: "Ideas", path: "/planner/ideas" }, - ], + path: "/planner/keywords", // Default to keywords, submenus shown as in-page navigation }); } - // Add Writer if enabled + // Add Writer if enabled (single item, no dropdown) if (moduleEnabled('writer')) { workflowItems.push({ icon: , name: "Writer", - subItems: [ - { name: "Dashboard", path: "/writer" }, - { name: "Tasks", path: "/writer/tasks" }, - { name: "Content", path: "/writer/content" }, - { name: "Images", path: "/writer/images" }, - { name: "Published", path: "/writer/published" }, - ], + path: "/writer/content", // Default to content, submenus shown as in-page navigation }); } - // Add Thinker if enabled - if (moduleEnabled('thinker')) { - workflowItems.push({ - icon: , - name: "Thinker", - subItems: [ - { name: "Dashboard", path: "/thinker" }, - { name: "Prompts", path: "/thinker/prompts" }, - { name: "Author Profiles", path: "/thinker/author-profiles" }, - { name: "Strategies", path: "/thinker/strategies" }, - { name: "Image Testing", path: "/thinker/image-testing" }, - ], - }); - } - - // Add Linker if enabled + // Add Linker if enabled (single item, no dropdown) if (moduleEnabled('linker')) { workflowItems.push({ icon: , name: "Linker", - subItems: [ - { name: "Dashboard", path: "/linker" }, - { name: "Content", path: "/linker/content" }, - ], + path: "/linker/content", }); } - // Add Optimizer if enabled + // Add Optimizer if enabled (single item, no dropdown) if (moduleEnabled('optimizer')) { workflowItems.push({ icon: , name: "Optimizer", - subItems: [ - { name: "Dashboard", path: "/optimizer" }, - { name: "Content", path: "/optimizer/content" }, - ], + path: "/optimizer/content", }); } - // Add Automation if enabled - if (moduleEnabled('automation')) { - workflowItems.push({ - icon: , - name: "Automation", - subItems: [ - { name: "Dashboard", path: "/automation" }, - { name: "Rules", path: "/automation/rules" }, - { name: "Tasks", path: "/automation/tasks" }, - ], - }); - } - - // Add Sites menu (always available) - workflowItems.push({ - icon: , - name: "Sites", - subItems: [ - { name: "All Sites", path: "/sites" }, - { name: "Create Site", path: "/sites/builder" }, - { name: "Blueprints", path: "/sites/blueprints" }, - ], - }); - return [ + // Dashboard is standalone (no section header) { - label: "OVERVIEW", + label: "", // Empty label for standalone Dashboard items: [ { icon: , name: "Dashboard", path: "/", }, - { - icon: , - name: "Industry / Sectors", - path: "/reference/industries", - }, ], }, { - label: "WORKFLOWS", + label: "SETUP", + items: setupItems, + }, + { + label: "WORKFLOW", items: workflowItems, }, - { - label: "ACCOUNT & SETTINGS", - items: [ + { + label: "SETTINGS", + items: [ { icon: , name: "Settings", @@ -215,28 +185,23 @@ const AppSidebar: React.FC = () => { { name: "Import / Export", path: "/settings/import-export" }, ], }, - { - icon: , - name: "Billing", - subItems: [ - { name: "Credits", path: "/billing/credits" }, - { name: "Transactions", path: "/billing/transactions" }, - { name: "Usage", path: "/billing/usage" }, - ], - }, - ], - }, - { - label: "HELP", - items: [ - { - icon: , - name: "Help & Documentation", - path: "/help", - }, - ], - }, - ]; + { + icon: , + name: "Billing", + subItems: [ + { name: "Credits", path: "/billing/credits" }, + { name: "Transactions", path: "/billing/transactions" }, + { name: "Usage", path: "/billing/usage" }, + ], + }, + { + icon: , + name: "Help & Documentation", + path: "/help", + }, + ], + }, + ]; }, [moduleEnabled]); // Admin section - only shown for users in aws-admin account @@ -585,20 +550,22 @@ const AppSidebar: React.FC = () => {