Files
dewedev/src/components/ToolCard.js
dwindown 2e67a2bca2 feat: comprehensive SEO optimization and GDPR compliance
- Added Terms of Service and Privacy Policy pages with contact info
- Implemented Google Analytics with Consent Mode v2 for GDPR compliance
- Created sitemap.xml and robots.txt for search engine optimization
- Added dynamic meta tags, Open Graph, and structured data (JSON-LD)
- Implemented GDPR consent banner with TCF 2.2 compatibility
- Enhanced sidebar with category-colored hover states and proper active/inactive styling
- Fixed all ESLint warnings for clean deployment
- Added comprehensive SEO utilities and privacy-first analytics tracking

Ready for production deployment with full legal compliance and SEO optimization.
2025-09-24 00:12:28 +07:00

109 lines
5.2 KiB
JavaScript

import React from 'react';
import { Link } from 'react-router-dom';
import { ArrowRight } from 'lucide-react';
import { getCategoryConfig } from '../config/tools';
const ToolCard = ({ icon: Icon, title, description, path, tags, category }) => {
const categoryConfig = getCategoryConfig(category);
// Define explicit hover classes for Tailwind CSS purging
const getHoverClasses = (category) => {
switch (category) {
case 'editor':
return {
border: 'hover:border-blue-300 dark:hover:border-blue-500',
shadow: 'hover:shadow-blue-500/20',
titleColor: 'group-hover:text-blue-600 dark:group-hover:text-blue-400',
arrowColor: 'group-hover:text-blue-600',
badgeColor: 'group-hover:bg-blue-100 dark:group-hover:bg-blue-900/30 group-hover:text-blue-700 dark:group-hover:text-blue-300'
};
case 'encoder':
return {
border: 'hover:border-purple-300 dark:hover:border-purple-500',
shadow: 'hover:shadow-purple-500/20',
titleColor: 'group-hover:text-purple-600 dark:group-hover:text-purple-400',
arrowColor: 'group-hover:text-purple-600',
badgeColor: 'group-hover:bg-purple-100 dark:group-hover:bg-purple-900/30 group-hover:text-purple-700 dark:group-hover:text-purple-300'
};
case 'formatter':
return {
border: 'hover:border-green-300 dark:hover:border-green-500',
shadow: 'hover:shadow-green-500/20',
titleColor: 'group-hover:text-green-600 dark:group-hover:text-green-400',
arrowColor: 'group-hover:text-green-600',
badgeColor: 'group-hover:bg-green-100 dark:group-hover:bg-green-900/30 group-hover:text-green-700 dark:group-hover:text-green-300'
};
case 'analyzer':
return {
border: 'hover:border-orange-300 dark:hover:border-orange-500',
shadow: 'hover:shadow-orange-500/20',
titleColor: 'group-hover:text-orange-600 dark:group-hover:text-orange-400',
arrowColor: 'group-hover:text-orange-600',
badgeColor: 'group-hover:bg-orange-100 dark:group-hover:bg-orange-900/30 group-hover:text-orange-700 dark:group-hover:text-orange-300'
};
default:
return {
border: 'hover:border-slate-300 dark:hover:border-slate-500',
shadow: 'hover:shadow-slate-500/20',
titleColor: 'group-hover:text-slate-600 dark:group-hover:text-slate-400',
arrowColor: 'group-hover:text-slate-600',
badgeColor: 'group-hover:bg-slate-100 dark:group-hover:bg-slate-700 group-hover:text-slate-700 dark:group-hover:text-slate-300'
};
}
};
const hoverClasses = getHoverClasses(category);
return (
<Link to={path} className="block group">
<div className={`relative overflow-hidden rounded-2xl bg-white/70 dark:bg-slate-800/70 backdrop-blur-sm border border-slate-200 dark:border-slate-700 ${hoverClasses.border} transition-all duration-300 hover:shadow-2xl ${hoverClasses.shadow} hover:-translate-y-1`}>
{/* Gradient overlay on hover */}
<div className={`absolute inset-0 bg-gradient-to-br ${categoryConfig.color} opacity-0 group-hover:opacity-5 transition-opacity duration-300`}></div>
<div className="relative p-6">
{/* Header */}
<div className="flex items-start justify-between mb-4">
<div className={`flex-shrink-0 p-3 rounded-xl bg-gradient-to-br ${categoryConfig.color} shadow-lg group-hover:scale-110 transition-transform duration-300`}>
<Icon className="h-6 w-6 text-white" />
</div>
<div className="flex-shrink-0 ml-4">
<ArrowRight className={`h-5 w-5 text-slate-400 ${hoverClasses.arrowColor} group-hover:translate-x-1 transition-all duration-300`} />
</div>
</div>
{/* Content */}
<div className="space-y-3">
<div className="flex items-center gap-2">
<h3 className={`text-xl font-bold text-slate-800 dark:text-white ${hoverClasses.titleColor} transition-colors`}>
{title}
</h3>
<span className={`px-2 py-1 text-xs font-medium bg-slate-100 dark:bg-slate-700 text-slate-600 dark:text-slate-300 rounded-full ${hoverClasses.badgeColor} transition-colors`}>
{categoryConfig.name}
</span>
</div>
<p className="text-slate-600 dark:text-slate-300 leading-relaxed group-hover:text-slate-700 dark:group-hover:text-slate-200 transition-colors">
{description}
</p>
{tags && tags.length > 0 && (
<div className="flex flex-wrap gap-2 pt-2">
{tags.map((tag, index) => (
<span
key={index}
className="px-3 py-1 text-xs font-medium bg-slate-50 dark:bg-slate-700/50 text-slate-500 dark:text-slate-400 rounded-full border border-slate-200 dark:border-slate-600 group-hover:border-slate-300 dark:group-hover:border-slate-500 transition-colors"
>
{tag}
</span>
))}
</div>
)}
</div>
</div>
</div>
</Link>
);
};
export default ToolCard;