frontend-refactor-1

This commit is contained in:
alorig
2025-11-20 08:58:38 +05:00
parent a0de0cf6b1
commit 8e7afa76cd
18 changed files with 1810 additions and 975 deletions

View File

@@ -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 (
<div className={`mt-8 pt-6 border-t border-gray-200 dark:border-gray-800 ${className}`}>
<div className="space-y-4">
{/* Metrics Grid */}
{metrics.length > 0 && (
<div className={`grid grid-cols-1 sm:grid-cols-2 ${metrics.length > 2 ? 'lg:grid-cols-3' : 'lg:grid-cols-2'} ${metrics.length > 3 ? 'xl:grid-cols-4' : ''} gap-4`}>
{metrics.map((metric, index) => (
<EnhancedMetricCard
key={index}
title={metric.title}
value={metric.value}
subtitle={metric.subtitle}
icon={metric.icon}
accentColor={metric.accentColor}
href={metric.href}
onClick={metric.onClick}
/>
))}
</div>
)}
{/* Progress Bar */}
{progress && (
<div className="space-y-2">
<ProgressBar
value={progress.value}
color={progress.color === 'success' ? 'success' : progress.color === 'warning' ? 'warning' : 'primary'}
size="md"
showLabel={true}
label={progress.label}
/>
</div>
)}
</div>
</div>
);
}

View File

@@ -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 (
<div className={`mb-6 ${className}`}>
<Tabs defaultTab={activeTabId}>
{(activeTabId, setActiveTab) => (
<TabList className="bg-gray-100 dark:bg-gray-900">
{tabs.map((tab) => {
const isActive = activeTabId === tab.path || location.pathname.startsWith(tab.path + '/');
return (
<Link
key={tab.path}
to={tab.path}
onClick={() => setActiveTab(tab.path)}
className="flex-1"
>
<Tab
tabId={tab.path}
isActive={isActive}
className="flex items-center justify-center gap-2"
>
{tab.icon && <span className="flex-shrink-0">{tab.icon}</span>}
<span>{tab.label}</span>
</Tab>
</Link>
);
})}
</TabList>
)}
</Tabs>
</div>
);
}