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.
This commit is contained in:
@@ -1,152 +1,187 @@
|
||||
import React, { useState } from 'react';
|
||||
import { Search, Code, Link2, FileText, Hash, RefreshCw, GitCompare, Type, Edit3, Table } from 'lucide-react';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { Search, Code, Terminal, Zap, Shield, Cpu } from 'lucide-react';
|
||||
import ToolCard from '../components/ToolCard';
|
||||
import { TOOLS, SITE_CONFIG } from '../config/tools';
|
||||
import { useAnalytics } from '../hooks/useAnalytics';
|
||||
|
||||
const Home = () => {
|
||||
console.log('🏠 NEW Home component loaded - Object Editor should be visible!');
|
||||
const [searchTerm, setSearchTerm] = useState('');
|
||||
const [mounted, setMounted] = useState(false);
|
||||
const { trackSearch } = useAnalytics();
|
||||
|
||||
const tools = [
|
||||
{
|
||||
icon: Edit3,
|
||||
title: 'Object Editor',
|
||||
description: 'Visual editor for JSON and PHP serialized objects with mindmap visualization',
|
||||
path: '/object-editor',
|
||||
tags: ['Visual', 'JSON', 'PHP', 'Objects', 'Editor']
|
||||
},
|
||||
{
|
||||
icon: Table,
|
||||
title: 'Table Editor',
|
||||
description: 'Import, edit, and export tabular data from URLs, files, or paste CSV/JSON',
|
||||
path: '/table-editor',
|
||||
tags: ['Table', 'CSV', 'JSON', 'Data', 'Editor']
|
||||
},
|
||||
{
|
||||
icon: Link2,
|
||||
title: 'URL Encoder/Decoder',
|
||||
description: 'Encode and decode URLs and query parameters',
|
||||
path: '/url',
|
||||
tags: ['URL', 'Encode', 'Decode']
|
||||
},
|
||||
{
|
||||
icon: Hash,
|
||||
title: 'Base64 Encoder/Decoder',
|
||||
description: 'Convert text to Base64 and back with support for files',
|
||||
path: '/base64',
|
||||
tags: ['Base64', 'Encode', 'Binary']
|
||||
},
|
||||
{
|
||||
icon: FileText,
|
||||
title: 'Code Beautifier/Minifier',
|
||||
description: 'Format and minify JSON, XML, SQL, CSS, and HTML code',
|
||||
path: '/beautifier',
|
||||
tags: ['Format', 'Minify', 'Beautify']
|
||||
},
|
||||
{
|
||||
icon: GitCompare,
|
||||
title: 'Text Diff Checker',
|
||||
description: 'Compare two texts and highlight differences line by line',
|
||||
path: '/diff',
|
||||
tags: ['Diff', 'Compare', 'Text']
|
||||
},
|
||||
{
|
||||
icon: Type,
|
||||
title: 'Text Length Checker',
|
||||
description: 'Analyze text length, word count, and other text statistics',
|
||||
path: '/text-length',
|
||||
tags: ['Text', 'Length', 'Statistics']
|
||||
useEffect(() => {
|
||||
setMounted(true);
|
||||
}, []);
|
||||
|
||||
// Handle search with analytics tracking
|
||||
const handleSearchChange = (e) => {
|
||||
const value = e.target.value;
|
||||
setSearchTerm(value);
|
||||
|
||||
// Track search after user stops typing (debounced)
|
||||
if (value.length > 2) {
|
||||
trackSearch(value);
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
const filteredTools = tools.filter(tool =>
|
||||
tool.title.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||
const filteredTools = TOOLS.filter(tool =>
|
||||
tool.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||
tool.description.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||
tool.tags.some(tag => tag.toLowerCase().includes(searchTerm.toLowerCase()))
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="max-w-6xl mx-auto">
|
||||
{/* Hero Section */}
|
||||
<div className="text-center mb-12">
|
||||
<h1 className="text-4xl font-bold text-gray-900 dark:text-white mb-4">
|
||||
Developer Tools
|
||||
</h1>
|
||||
<p className="text-xl text-gray-600 dark:text-gray-300 mb-8">
|
||||
Essential utilities for web developers - fast, local, and easy to use
|
||||
</p>
|
||||
|
||||
{/* Search */}
|
||||
<div className="relative max-w-md mx-auto">
|
||||
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 h-5 w-5 text-gray-400" />
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Search tools..."
|
||||
value={searchTerm}
|
||||
onChange={(e) => setSearchTerm(e.target.value)}
|
||||
className="w-full pl-10 pr-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-primary-500 focus:border-transparent"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Tools Grid */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
{filteredTools.map((tool, index) => (
|
||||
<ToolCard
|
||||
key={index}
|
||||
icon={tool.icon}
|
||||
title={tool.title}
|
||||
description={tool.description}
|
||||
path={tool.path}
|
||||
tags={tool.tags}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* No Results */}
|
||||
{filteredTools.length === 0 && (
|
||||
<div className="text-center py-12">
|
||||
<p className="text-gray-500 dark:text-gray-400 text-lg">
|
||||
No tools found matching "{searchTerm}"
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Features */}
|
||||
<div className="mt-16 grid grid-cols-1 md:grid-cols-3 gap-8">
|
||||
<div className="text-center">
|
||||
<div className="bg-primary-100 dark:bg-primary-900 rounded-full w-16 h-16 flex items-center justify-center mx-auto mb-4">
|
||||
<RefreshCw className="h-8 w-8 text-primary-600" />
|
||||
<div className="min-h-screen bg-gradient-to-br from-slate-50 via-blue-50 to-indigo-50 dark:from-slate-900 dark:via-slate-800 dark:to-indigo-900">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
{/* Hero Section */}
|
||||
<div className={`text-center pt-16 pb-20 transition-all duration-1000 ${mounted ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-8'}`}>
|
||||
{/* Terminal-style header */}
|
||||
<div className="inline-flex items-center gap-2 px-4 py-2 bg-slate-800 dark:bg-slate-700 rounded-full text-green-400 font-mono text-sm mb-8 shadow-lg">
|
||||
<Terminal className="h-4 w-4" />
|
||||
<span>~/dewe.dev $</span>
|
||||
<span className="animate-pulse">_</span>
|
||||
</div>
|
||||
<h3 className="text-lg font-semibold text-gray-900 dark:text-white mb-2">
|
||||
Lightning Fast
|
||||
</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300">
|
||||
All processing happens locally in your browser for maximum speed and privacy
|
||||
|
||||
<h1 className="text-5xl md:text-7xl font-bold bg-gradient-to-r from-blue-600 via-purple-600 to-indigo-600 bg-clip-text text-transparent mb-6">
|
||||
{SITE_CONFIG.title}
|
||||
</h1>
|
||||
|
||||
<p className="text-xl md:text-2xl text-slate-600 dark:text-slate-300 mb-4 max-w-3xl mx-auto leading-relaxed">
|
||||
{SITE_CONFIG.subtitle}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="text-center">
|
||||
<div className="bg-primary-100 dark:bg-primary-900 rounded-full w-16 h-16 flex items-center justify-center mx-auto mb-4">
|
||||
<FileText className="h-8 w-8 text-primary-600" />
|
||||
|
||||
<p className="text-lg text-slate-500 dark:text-slate-400 mb-12 max-w-2xl mx-auto">
|
||||
{SITE_CONFIG.slogan} • {SITE_CONFIG.description}
|
||||
</p>
|
||||
|
||||
{/* Enhanced Search */}
|
||||
<div className="relative max-w-lg mx-auto mb-8">
|
||||
<div className="absolute inset-0 bg-gradient-to-r from-blue-500 to-purple-500 rounded-2xl blur opacity-20"></div>
|
||||
<div className="relative">
|
||||
<Search className="absolute left-4 top-1/2 transform -translate-y-1/2 h-5 w-5 text-slate-400" />
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Search tools..."
|
||||
value={searchTerm}
|
||||
onChange={handleSearchChange}
|
||||
className="w-full pl-12 pr-6 py-4 bg-white/80 dark:bg-slate-800/80 backdrop-blur-sm border border-slate-200 dark:border-slate-600 rounded-2xl text-slate-900 dark:text-slate-100 placeholder-slate-500 focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all duration-300 shadow-lg"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<h3 className="text-lg font-semibold text-gray-900 dark:text-white mb-2">
|
||||
Handle Large Files
|
||||
</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300">
|
||||
Process large text files and data with ease, no size limitations
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="text-center">
|
||||
<div className="bg-primary-100 dark:bg-primary-900 rounded-full w-16 h-16 flex items-center justify-center mx-auto mb-4">
|
||||
<Code className="h-8 w-8 text-primary-600" />
|
||||
|
||||
{/* Stats */}
|
||||
<div className="flex justify-center items-center gap-8 text-sm text-slate-500 dark:text-slate-400">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="w-2 h-2 bg-green-500 rounded-full animate-pulse"></div>
|
||||
<span>{SITE_CONFIG.totalTools} Tools Available</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="w-2 h-2 bg-blue-500 rounded-full"></div>
|
||||
<span>100% Client-Side</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="w-2 h-2 bg-purple-500 rounded-full"></div>
|
||||
<span>Zero Data Collection</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Tools Grid */}
|
||||
<div className={`transition-all duration-1000 delay-300 ${mounted ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-8'}`}>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8 mb-20">
|
||||
{filteredTools.map((tool, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className={`transition-all duration-500 ${mounted ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-8'}`}
|
||||
style={{ transitionDelay: `${400 + index * 100}ms` }}
|
||||
>
|
||||
<ToolCard
|
||||
icon={tool.icon}
|
||||
title={tool.name}
|
||||
description={tool.description}
|
||||
path={tool.path}
|
||||
tags={tool.tags}
|
||||
category={tool.category}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* No Results */}
|
||||
{filteredTools.length === 0 && (
|
||||
<div className="text-center py-20">
|
||||
<div className="text-6xl mb-4">🔍</div>
|
||||
<p className="text-slate-500 dark:text-slate-400 text-xl mb-2">
|
||||
No tools found matching "{searchTerm}"
|
||||
</p>
|
||||
<p className="text-slate-400 dark:text-slate-500">
|
||||
Try searching for "editor", "encode", or "format"
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Features Section */}
|
||||
<div className={`py-20 transition-all duration-1000 delay-700 ${mounted ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-8'}`}>
|
||||
<div className="text-center mb-16">
|
||||
<h2 className="text-3xl md:text-4xl font-bold text-slate-800 dark:text-white mb-4">
|
||||
Built for Developers
|
||||
</h2>
|
||||
<p className="text-xl text-slate-600 dark:text-slate-300 max-w-2xl mx-auto">
|
||||
Every tool is crafted with developer experience and performance in mind
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
<div className="group text-center p-8 rounded-2xl bg-white/50 dark:bg-slate-800/50 backdrop-blur-sm border border-slate-200 dark:border-slate-700 hover:border-blue-300 dark:hover:border-blue-600 transition-all duration-300 hover:shadow-xl hover:shadow-blue-500/10">
|
||||
<div className="bg-gradient-to-br from-blue-500 to-blue-600 rounded-2xl w-16 h-16 flex items-center justify-center mx-auto mb-6 group-hover:scale-110 transition-transform duration-300">
|
||||
<Zap className="h-8 w-8 text-white" />
|
||||
</div>
|
||||
<h3 className="text-xl font-bold text-slate-800 dark:text-white mb-3">
|
||||
Lightning Fast
|
||||
</h3>
|
||||
<p className="text-slate-600 dark:text-slate-300 leading-relaxed">
|
||||
Optimized algorithms and local processing ensure instant results
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="group text-center p-8 rounded-2xl bg-white/50 dark:bg-slate-800/50 backdrop-blur-sm border border-slate-200 dark:border-slate-700 hover:border-purple-300 dark:hover:border-purple-600 transition-all duration-300 hover:shadow-xl hover:shadow-purple-500/10">
|
||||
<div className="bg-gradient-to-br from-purple-500 to-purple-600 rounded-2xl w-16 h-16 flex items-center justify-center mx-auto mb-6 group-hover:scale-110 transition-transform duration-300">
|
||||
<Shield className="h-8 w-8 text-white" />
|
||||
</div>
|
||||
<h3 className="text-xl font-bold text-slate-800 dark:text-white mb-3">
|
||||
Privacy First
|
||||
</h3>
|
||||
<p className="text-slate-600 dark:text-slate-300 leading-relaxed">
|
||||
Your data never leaves your browser. Zero tracking, zero storage
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="group text-center p-8 rounded-2xl bg-white/50 dark:bg-slate-800/50 backdrop-blur-sm border border-slate-200 dark:border-slate-700 hover:border-green-300 dark:hover:border-green-600 transition-all duration-300 hover:shadow-xl hover:shadow-green-500/10">
|
||||
<div className="bg-gradient-to-br from-green-500 to-green-600 rounded-2xl w-16 h-16 flex items-center justify-center mx-auto mb-6 group-hover:scale-110 transition-transform duration-300">
|
||||
<Cpu className="h-8 w-8 text-white" />
|
||||
</div>
|
||||
<h3 className="text-xl font-bold text-slate-800 dark:text-white mb-3">
|
||||
No Limits
|
||||
</h3>
|
||||
<p className="text-slate-600 dark:text-slate-300 leading-relaxed">
|
||||
Handle massive files and complex data without restrictions
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="group text-center p-8 rounded-2xl bg-white/50 dark:bg-slate-800/50 backdrop-blur-sm border border-slate-200 dark:border-slate-700 hover:border-indigo-300 dark:hover:border-indigo-600 transition-all duration-300 hover:shadow-xl hover:shadow-indigo-500/10">
|
||||
<div className="bg-gradient-to-br from-indigo-500 to-indigo-600 rounded-2xl w-16 h-16 flex items-center justify-center mx-auto mb-6 group-hover:scale-110 transition-transform duration-300">
|
||||
<Code className="h-8 w-8 text-white" />
|
||||
</div>
|
||||
<h3 className="text-xl font-bold text-slate-800 dark:text-white mb-3">
|
||||
Dev Focused
|
||||
</h3>
|
||||
<p className="text-slate-600 dark:text-slate-300 leading-relaxed">
|
||||
Syntax highlighting, shortcuts, and workflows developers love
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<h3 className="text-lg font-semibold text-gray-900 dark:text-white mb-2">
|
||||
Developer Friendly
|
||||
</h3>
|
||||
<p className="text-gray-600 dark:text-gray-300">
|
||||
Clean interface with syntax highlighting and easy copy-paste functionality
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
265
src/pages/PrivacyPolicy.js
Normal file
265
src/pages/PrivacyPolicy.js
Normal file
@@ -0,0 +1,265 @@
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { ArrowLeft, Shield, Lock, Eye, Server, Cookie, BarChart3, Globe } from 'lucide-react';
|
||||
import { SITE_CONFIG } from '../config/tools';
|
||||
|
||||
const PrivacyPolicy = () => {
|
||||
return (
|
||||
<div className="min-h-screen bg-gradient-to-br from-slate-50 via-blue-50 to-indigo-50 dark:from-slate-900 dark:via-slate-800 dark:to-indigo-900">
|
||||
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
|
||||
{/* Header */}
|
||||
<div className="mb-8">
|
||||
<Link
|
||||
to="/"
|
||||
className="inline-flex items-center gap-2 text-blue-600 hover:text-blue-700 dark:text-blue-400 dark:hover:text-blue-300 transition-colors mb-6"
|
||||
>
|
||||
<ArrowLeft className="h-4 w-4" />
|
||||
Back to Home
|
||||
</Link>
|
||||
|
||||
<div className="flex items-center gap-3 mb-4">
|
||||
<div className="p-3 bg-gradient-to-br from-green-500 to-emerald-500 rounded-xl shadow-lg">
|
||||
<Lock className="h-6 w-6 text-white" />
|
||||
</div>
|
||||
<div>
|
||||
<h1 className="text-3xl font-bold text-slate-800 dark:text-white">
|
||||
Privacy Policy
|
||||
</h1>
|
||||
<p className="text-slate-600 dark:text-slate-300">
|
||||
Last updated: {new Date().toLocaleDateString()}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Content */}
|
||||
<div className="bg-white/70 dark:bg-slate-800/70 backdrop-blur-sm rounded-2xl border border-slate-200 dark:border-slate-700 p-8 shadow-xl">
|
||||
<div className="prose prose-slate dark:prose-invert max-w-none">
|
||||
|
||||
{/* Privacy-First Commitment */}
|
||||
<section className="mb-8">
|
||||
<div className="bg-gradient-to-r from-green-50 to-blue-50 dark:from-green-900/20 dark:to-blue-900/20 rounded-xl p-6 mb-6">
|
||||
<h2 className="text-2xl font-bold text-slate-800 dark:text-white mb-4 flex items-center gap-3">
|
||||
<Shield className="h-6 w-6 text-green-600" />
|
||||
Our Privacy-First Commitment
|
||||
</h2>
|
||||
<p className="text-slate-700 dark:text-slate-200 text-lg leading-relaxed mb-4">
|
||||
At {SITE_CONFIG.title}, "Privacy-First" isn't just a marketing term—it's our core architectural principle. Your data privacy is protected by design, not by policy alone.
|
||||
</p>
|
||||
<div className="grid md:grid-cols-2 gap-4">
|
||||
<div className="flex items-start gap-3">
|
||||
<div className="p-2 bg-green-100 dark:bg-green-900/30 rounded-lg">
|
||||
<Server className="h-5 w-5 text-green-600" />
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="font-semibold text-slate-800 dark:text-white">100% Client-Side</h3>
|
||||
<p className="text-sm text-slate-600 dark:text-slate-300">All processing happens in your browser</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-start gap-3">
|
||||
<div className="p-2 bg-blue-100 dark:bg-blue-900/30 rounded-lg">
|
||||
<Lock className="h-5 w-5 text-blue-600" />
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="font-semibold text-slate-800 dark:text-white">Zero Data Upload</h3>
|
||||
<p className="text-sm text-slate-600 dark:text-slate-300">Your sensitive data never leaves your device</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="mb-8">
|
||||
<h2 className="text-xl font-semibold text-slate-800 dark:text-white mb-4 flex items-center gap-2">
|
||||
<Eye className="h-5 w-5 text-blue-600" />
|
||||
1. Information We Collect
|
||||
</h2>
|
||||
|
||||
<div className="space-y-6">
|
||||
<div className="bg-red-50 dark:bg-red-900/20 rounded-lg p-4">
|
||||
<h3 className="font-semibold text-red-800 dark:text-red-200 mb-2">
|
||||
❌ What We DON'T Collect:
|
||||
</h3>
|
||||
<ul className="list-disc list-inside text-red-700 dark:text-red-300 space-y-1 text-sm">
|
||||
<li>Your input data (JSON, CSV, URLs, text, etc.)</li>
|
||||
<li>Files you upload or paste into our tools</li>
|
||||
<li>Personal information (name, email, address)</li>
|
||||
<li>Login credentials or user accounts</li>
|
||||
<li>IP addresses or device fingerprints</li>
|
||||
<li>Browsing history or cross-site tracking</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div className="bg-green-50 dark:bg-green-900/20 rounded-lg p-4">
|
||||
<h3 className="font-semibold text-green-800 dark:text-green-200 mb-2">
|
||||
✅ What We DO Collect (via Google Analytics):
|
||||
</h3>
|
||||
<ul className="list-disc list-inside text-green-700 dark:text-green-300 space-y-1 text-sm">
|
||||
<li>Anonymous page views and session duration</li>
|
||||
<li>Which tools are most popular (aggregated data only)</li>
|
||||
<li>General geographic region (country/state level)</li>
|
||||
<li>Browser type and device type (for compatibility)</li>
|
||||
<li>Referral sources (how you found our site)</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="mb-8">
|
||||
<h2 className="text-xl font-semibold text-slate-800 dark:text-white mb-4 flex items-center gap-2">
|
||||
<BarChart3 className="h-5 w-5 text-purple-600" />
|
||||
2. Google Analytics Usage
|
||||
</h2>
|
||||
<p className="text-slate-600 dark:text-slate-300 leading-relaxed mb-4">
|
||||
We use Google Analytics to understand how our tools are used and to improve the service. This helps us answer questions like:
|
||||
</p>
|
||||
<ul className="list-disc list-inside text-slate-600 dark:text-slate-300 space-y-2 ml-4 mb-4">
|
||||
<li>Which tools are most helpful to developers?</li>
|
||||
<li>Are there performance issues on certain devices?</li>
|
||||
<li>How can we improve the user experience?</li>
|
||||
</ul>
|
||||
<div className="bg-blue-50 dark:bg-blue-900/20 rounded-lg p-4">
|
||||
<p className="text-blue-800 dark:text-blue-200 text-sm">
|
||||
<strong>Important:</strong> Google Analytics only sees that someone visited "dewe.dev/beautifier" - it never sees the actual JSON code you're beautifying or any data you process with our tools.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="mb-8">
|
||||
<h2 className="text-xl font-semibold text-slate-800 dark:text-white mb-4 flex items-center gap-2">
|
||||
<Server className="h-5 w-5 text-indigo-600" />
|
||||
3. How Our Tools Work
|
||||
</h2>
|
||||
<div className="bg-slate-50 dark:bg-slate-800/50 rounded-lg p-6">
|
||||
<h3 className="font-semibold text-slate-800 dark:text-white mb-3">Technical Architecture:</h3>
|
||||
<div className="space-y-3 text-sm">
|
||||
<div className="flex items-start gap-3">
|
||||
<span className="bg-green-100 dark:bg-green-900/30 text-green-700 dark:text-green-300 px-2 py-1 rounded text-xs font-medium">CLIENT</span>
|
||||
<p className="text-slate-600 dark:text-slate-300">Your browser downloads our JavaScript code</p>
|
||||
</div>
|
||||
<div className="flex items-start gap-3">
|
||||
<span className="bg-blue-100 dark:bg-blue-900/30 text-blue-700 dark:text-blue-300 px-2 py-1 rounded text-xs font-medium">LOCAL</span>
|
||||
<p className="text-slate-600 dark:text-slate-300">All processing happens locally in your browser's memory</p>
|
||||
</div>
|
||||
<div className="flex items-start gap-3">
|
||||
<span className="bg-purple-100 dark:bg-purple-900/30 text-purple-700 dark:text-purple-300 px-2 py-1 rounded text-xs font-medium">SECURE</span>
|
||||
<p className="text-slate-600 dark:text-slate-300">No data transmission to our servers for processing</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="mb-8">
|
||||
<h2 className="text-xl font-semibold text-slate-800 dark:text-white mb-4 flex items-center gap-2">
|
||||
<Cookie className="h-5 w-5 text-orange-600" />
|
||||
4. Cookies and Local Storage
|
||||
</h2>
|
||||
<p className="text-slate-600 dark:text-slate-300 leading-relaxed mb-4">
|
||||
We use minimal cookies and local storage for:
|
||||
</p>
|
||||
<ul className="list-disc list-inside text-slate-600 dark:text-slate-300 space-y-2 ml-4">
|
||||
<li><strong>Google Analytics:</strong> Anonymous tracking cookies (you can opt-out)</li>
|
||||
<li><strong>Theme Preference:</strong> Remembering if you prefer dark/light mode</li>
|
||||
<li><strong>No Personal Data:</strong> We never store your processed data locally</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section className="mb-8">
|
||||
<h2 className="text-xl font-semibold text-slate-800 dark:text-white mb-4 flex items-center gap-2">
|
||||
<Globe className="h-5 w-5 text-teal-600" />
|
||||
5. Future Advertising (Google AdSense)
|
||||
</h2>
|
||||
<div className="bg-amber-50 dark:bg-amber-900/20 rounded-lg p-4 mb-4">
|
||||
<h3 className="font-semibold text-amber-800 dark:text-amber-200 mb-2">
|
||||
🔮 Planned Implementation:
|
||||
</h3>
|
||||
<p className="text-amber-700 dark:text-amber-300 text-sm leading-relaxed mb-3">
|
||||
To keep our tools free, we plan to display Google AdSense advertisements. When implemented:
|
||||
</p>
|
||||
<ul className="list-disc list-inside text-amber-700 dark:text-amber-300 space-y-1 text-sm">
|
||||
<li>Ads will be clearly marked and non-intrusive</li>
|
||||
<li>No impact on tool functionality or performance</li>
|
||||
<li>Google may use cookies for ad personalization</li>
|
||||
<li>You can opt-out of personalized ads via Google settings</li>
|
||||
<li><strong>We will NEVER share your tool usage data with advertisers</strong></li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="mb-8">
|
||||
<h2 className="text-xl font-semibold text-slate-800 dark:text-white mb-4">
|
||||
6. Your Rights and Controls
|
||||
</h2>
|
||||
<div className="grid md:grid-cols-2 gap-4">
|
||||
<div className="bg-blue-50 dark:bg-blue-900/20 rounded-lg p-4">
|
||||
<h3 className="font-semibold text-blue-800 dark:text-blue-200 mb-2">Analytics Opt-Out:</h3>
|
||||
<p className="text-blue-700 dark:text-blue-300 text-sm">
|
||||
Install browser extensions like uBlock Origin or use Google's opt-out tools to disable analytics tracking.
|
||||
</p>
|
||||
</div>
|
||||
<div className="bg-green-50 dark:bg-green-900/20 rounded-lg p-4">
|
||||
<h3 className="font-semibold text-green-800 dark:text-green-200 mb-2">Data Control:</h3>
|
||||
<p className="text-green-700 dark:text-green-300 text-sm">
|
||||
Since we don't collect your data, there's nothing to delete or export. Your data stays with you.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="mb-8">
|
||||
<h2 className="text-xl font-semibold text-slate-800 dark:text-white mb-4">
|
||||
7. Third-Party Services
|
||||
</h2>
|
||||
<div className="space-y-4">
|
||||
<div className="border-l-4 border-blue-500 pl-4">
|
||||
<h3 className="font-semibold text-slate-800 dark:text-white">Google Analytics</h3>
|
||||
<p className="text-slate-600 dark:text-slate-300 text-sm">
|
||||
Privacy Policy: <a href="https://policies.google.com/privacy" className="text-blue-600 hover:underline" target="_blank" rel="noopener noreferrer">https://policies.google.com/privacy</a>
|
||||
</p>
|
||||
</div>
|
||||
<div className="border-l-4 border-green-500 pl-4">
|
||||
<h3 className="font-semibold text-slate-800 dark:text-white">Google AdSense (Future)</h3>
|
||||
<p className="text-slate-600 dark:text-slate-300 text-sm">
|
||||
Privacy Policy: <a href="https://policies.google.com/privacy" className="text-blue-600 hover:underline" target="_blank" rel="noopener noreferrer">https://policies.google.com/privacy</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="mb-8">
|
||||
<h2 className="text-xl font-semibold text-slate-800 dark:text-white mb-4">
|
||||
8. Changes to This Policy
|
||||
</h2>
|
||||
<p className="text-slate-600 dark:text-slate-300 leading-relaxed">
|
||||
We may update this privacy policy from time to time. We will notify users of any material changes by updating the "Last updated" date at the top of this policy. Your continued use of the service after any changes constitutes acceptance of the new policy.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 className="text-xl font-semibold text-slate-800 dark:text-white mb-4">
|
||||
9. Contact Us
|
||||
</h2>
|
||||
<p className="text-slate-600 dark:text-slate-300 leading-relaxed">
|
||||
If you have any questions about this Privacy Policy or our privacy practices, please contact us at{' '}
|
||||
<a href="mailto:dewe.developer@gmail.com" className="text-blue-600 hover:text-blue-700 dark:text-blue-400 dark:hover:text-blue-300 underline">
|
||||
dewe.developer@gmail.com
|
||||
</a>
|
||||
{' '}or visit {SITE_CONFIG.domain}.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Footer */}
|
||||
<div className="mt-8 text-center">
|
||||
<p className="text-sm text-slate-500 dark:text-slate-400">
|
||||
© {SITE_CONFIG.year} {SITE_CONFIG.title} • Your privacy is our priority
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default PrivacyPolicy;
|
||||
@@ -1276,13 +1276,45 @@ const TableEditor = () => {
|
||||
})),
|
||||
);
|
||||
|
||||
// Auto-scroll to the right to show the new column
|
||||
// Auto-trigger header editing for the new column
|
||||
setEditingHeader(newColumnId);
|
||||
|
||||
// Auto-scroll to the right to show the new column and focus on header input
|
||||
setTimeout(() => {
|
||||
const tableContainer = document.querySelector(".overflow-auto");
|
||||
if (tableContainer) {
|
||||
tableContainer.scrollLeft = tableContainer.scrollWidth;
|
||||
// Try multiple selectors to find the table container
|
||||
const selectors = [
|
||||
'[class*="overflow-auto"][class*="max-h-"]',
|
||||
'.overflow-auto',
|
||||
'div[class*="overflow-auto"]'
|
||||
];
|
||||
|
||||
let tableContainer = null;
|
||||
for (const selector of selectors) {
|
||||
tableContainer = document.querySelector(selector);
|
||||
if (tableContainer) break;
|
||||
}
|
||||
}, 100);
|
||||
|
||||
if (tableContainer) {
|
||||
// Check if horizontal scrolling is needed
|
||||
const needsScroll = tableContainer.scrollWidth > tableContainer.clientWidth;
|
||||
if (needsScroll) {
|
||||
// Smooth scroll to the far right to show the new column
|
||||
tableContainer.scrollTo({
|
||||
left: tableContainer.scrollWidth - tableContainer.clientWidth,
|
||||
behavior: 'smooth'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Focus on the header input field after scroll
|
||||
setTimeout(() => {
|
||||
const headerInput = document.querySelector(`input[value="${newColumn.name}"]`);
|
||||
if (headerInput) {
|
||||
headerInput.focus();
|
||||
headerInput.select(); // Select all text for easy replacement
|
||||
}
|
||||
}, 100);
|
||||
}, 200);
|
||||
};
|
||||
|
||||
// Delete selected rows
|
||||
@@ -2419,7 +2451,7 @@ const TableEditor = () => {
|
||||
{editingCell?.rowId === row.id &&
|
||||
editingCell?.columnId === column.id ? (
|
||||
(() => {
|
||||
const cellValue = row[column.id] || "";
|
||||
const cellValue = String(row[column.id] || "");
|
||||
const isLongValue =
|
||||
cellValue.length > 100 ||
|
||||
cellValue.includes("\n");
|
||||
@@ -2474,7 +2506,7 @@ const TableEditor = () => {
|
||||
const format = detectCellFormat(
|
||||
row[column.id],
|
||||
);
|
||||
const cellValue = row[column.id] || "";
|
||||
const cellValue = String(row[column.id] || "");
|
||||
const isLongValue = cellValue.length > 50;
|
||||
|
||||
if (format) {
|
||||
@@ -2540,20 +2572,25 @@ const TableEditor = () => {
|
||||
))}
|
||||
|
||||
{/* System Row - Add Row */}
|
||||
<tr className="border-t-2 border-dashed border-gray-300 dark:border-gray-600 hover:bg-blue-50 dark:hover:bg-blue-900/20">
|
||||
<td
|
||||
colSpan={columns.length + 2}
|
||||
className="text-center py-4"
|
||||
>
|
||||
<tr className="border-t-2 border-dashed border-gray-300 dark:border-gray-600">
|
||||
{/* Sticky Add Row button on the left */}
|
||||
<td className="sticky left-0 bg-white dark:bg-gray-800 z-20 py-4 px-4">
|
||||
<button
|
||||
onClick={addRow}
|
||||
className="flex items-center justify-center gap-2 text-gray-500 hover:text-blue-600 px-4 py-2 rounded-lg transition-colors group"
|
||||
className="flex items-center justify-center gap-2 text-gray-500 hover:text-blue-600 px-3 py-2 rounded-lg transition-colors group whitespace-nowrap"
|
||||
title="Add new row"
|
||||
>
|
||||
<Plus className="h-4 w-4 group-hover:scale-110 transition-transform" />
|
||||
<span className="text-sm font-medium">Add Row</span>
|
||||
</button>
|
||||
</td>
|
||||
{/* Empty cells to fill the rest of the row */}
|
||||
<td
|
||||
colSpan={columns.length + 1}
|
||||
className="py-4"
|
||||
>
|
||||
{/* Empty space for visual consistency */}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
170
src/pages/TermsOfService.js
Normal file
170
src/pages/TermsOfService.js
Normal file
@@ -0,0 +1,170 @@
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { ArrowLeft, Shield, Code, Globe } from 'lucide-react';
|
||||
import { SITE_CONFIG } from '../config/tools';
|
||||
|
||||
const TermsOfService = () => {
|
||||
return (
|
||||
<div className="min-h-screen bg-gradient-to-br from-slate-50 via-blue-50 to-indigo-50 dark:from-slate-900 dark:via-slate-800 dark:to-indigo-900">
|
||||
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
|
||||
{/* Header */}
|
||||
<div className="mb-8">
|
||||
<Link
|
||||
to="/"
|
||||
className="inline-flex items-center gap-2 text-blue-600 hover:text-blue-700 dark:text-blue-400 dark:hover:text-blue-300 transition-colors mb-6"
|
||||
>
|
||||
<ArrowLeft className="h-4 w-4" />
|
||||
Back to Home
|
||||
</Link>
|
||||
|
||||
<div className="flex items-center gap-3 mb-4">
|
||||
<div className="p-3 bg-gradient-to-br from-blue-500 to-purple-500 rounded-xl shadow-lg">
|
||||
<Shield className="h-6 w-6 text-white" />
|
||||
</div>
|
||||
<div>
|
||||
<h1 className="text-3xl font-bold text-slate-800 dark:text-white">
|
||||
Terms of Service
|
||||
</h1>
|
||||
<p className="text-slate-600 dark:text-slate-300">
|
||||
Last updated: {new Date().toLocaleDateString()}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Content */}
|
||||
<div className="bg-white/70 dark:bg-slate-800/70 backdrop-blur-sm rounded-2xl border border-slate-200 dark:border-slate-700 p-8 shadow-xl">
|
||||
<div className="prose prose-slate dark:prose-invert max-w-none">
|
||||
|
||||
<section className="mb-8">
|
||||
<h2 className="text-xl font-semibold text-slate-800 dark:text-white mb-4 flex items-center gap-2">
|
||||
<Code className="h-5 w-5 text-blue-600" />
|
||||
1. Acceptance of Terms
|
||||
</h2>
|
||||
<p className="text-slate-600 dark:text-slate-300 leading-relaxed">
|
||||
By accessing and using {SITE_CONFIG.title} ("{SITE_CONFIG.domain}"), you accept and agree to be bound by the terms and provision of this agreement. If you do not agree to abide by the above, please do not use this service.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section className="mb-8">
|
||||
<h2 className="text-xl font-semibold text-slate-800 dark:text-white mb-4 flex items-center gap-2">
|
||||
<Globe className="h-5 w-5 text-green-600" />
|
||||
2. Service Description
|
||||
</h2>
|
||||
<p className="text-slate-600 dark:text-slate-300 leading-relaxed mb-4">
|
||||
{SITE_CONFIG.title} provides a collection of developer tools including but not limited to:
|
||||
</p>
|
||||
<ul className="list-disc list-inside text-slate-600 dark:text-slate-300 space-y-2 ml-4">
|
||||
<li>Object and Table Editors for JSON, CSV, and other data formats</li>
|
||||
<li>URL and Base64 Encoders/Decoders</li>
|
||||
<li>Code Beautifiers and Minifiers</li>
|
||||
<li>Text Analysis and Comparison Tools</li>
|
||||
<li>Other web-based developer utilities</li>
|
||||
</ul>
|
||||
<p className="text-slate-600 dark:text-slate-300 leading-relaxed mt-4">
|
||||
All tools run entirely in your browser - no data is sent to our servers for processing.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section className="mb-8">
|
||||
<h2 className="text-xl font-semibold text-slate-800 dark:text-white mb-4">
|
||||
3. Privacy-First Approach
|
||||
</h2>
|
||||
<div className="bg-blue-50 dark:bg-blue-900/20 rounded-lg p-4 mb-4">
|
||||
<p className="text-blue-800 dark:text-blue-200 font-medium mb-2">
|
||||
🔒 What "Privacy-First" means at {SITE_CONFIG.title}:
|
||||
</p>
|
||||
<ul className="list-disc list-inside text-blue-700 dark:text-blue-300 space-y-1 text-sm">
|
||||
<li><strong>Client-Side Processing:</strong> All tools process your data locally in your browser</li>
|
||||
<li><strong>No Data Upload:</strong> Your sensitive data never leaves your device</li>
|
||||
<li><strong>No Storage:</strong> We don't store, cache, or log your input data</li>
|
||||
<li><strong>Minimal Analytics:</strong> We only collect anonymous usage statistics via Google Analytics</li>
|
||||
<li><strong>No Tracking:</strong> No user accounts, no personal data collection</li>
|
||||
</ul>
|
||||
</div>
|
||||
<p className="text-slate-600 dark:text-slate-300 leading-relaxed">
|
||||
We use Google Analytics to understand how our tools are used (page views, popular tools, etc.) but we never track or store the actual data you process with our tools.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section className="mb-8">
|
||||
<h2 className="text-xl font-semibold text-slate-800 dark:text-white mb-4">
|
||||
4. Use License
|
||||
</h2>
|
||||
<p className="text-slate-600 dark:text-slate-300 leading-relaxed">
|
||||
Permission is granted to temporarily use {SITE_CONFIG.title} for personal and commercial purposes. This is the grant of a license, not a transfer of title, and under this license you may not:
|
||||
</p>
|
||||
<ul className="list-disc list-inside text-slate-600 dark:text-slate-300 space-y-2 ml-4 mt-4">
|
||||
<li>Use the service for any illegal or unauthorized purpose</li>
|
||||
<li>Attempt to reverse engineer or extract source code</li>
|
||||
<li>Use automated tools to overload our servers</li>
|
||||
<li>Redistribute or resell access to the service</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section className="mb-8">
|
||||
<h2 className="text-xl font-semibold text-slate-800 dark:text-white mb-4">
|
||||
5. Disclaimer
|
||||
</h2>
|
||||
<p className="text-slate-600 dark:text-slate-300 leading-relaxed">
|
||||
The materials on {SITE_CONFIG.title} are provided on an 'as is' basis. {SITE_CONFIG.title} makes no warranties, expressed or implied, and hereby disclaims and negates all other warranties including without limitation, implied warranties or conditions of merchantability, fitness for a particular purpose, or non-infringement of intellectual property or other violation of rights.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section className="mb-8">
|
||||
<h2 className="text-xl font-semibold text-slate-800 dark:text-white mb-4">
|
||||
6. Limitations
|
||||
</h2>
|
||||
<p className="text-slate-600 dark:text-slate-300 leading-relaxed">
|
||||
In no event shall {SITE_CONFIG.title} or its suppliers be liable for any damages (including, without limitation, damages for loss of data or profit, or due to business interruption) arising out of the use or inability to use the materials on {SITE_CONFIG.title}, even if {SITE_CONFIG.title} or an authorized representative has been notified orally or in writing of the possibility of such damage.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section className="mb-8">
|
||||
<h2 className="text-xl font-semibold text-slate-800 dark:text-white mb-4">
|
||||
7. Future Monetization
|
||||
</h2>
|
||||
<div className="bg-amber-50 dark:bg-amber-900/20 rounded-lg p-4">
|
||||
<p className="text-amber-800 dark:text-amber-200 leading-relaxed">
|
||||
<strong>Transparency Notice:</strong> We plan to implement Google AdSense advertisements in the future to support the free operation of this service. When implemented, ads will be clearly marked and will not interfere with tool functionality. Our privacy-first approach will remain unchanged - we will never sell or share your usage data with advertisers.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="mb-8">
|
||||
<h2 className="text-xl font-semibold text-slate-800 dark:text-white mb-4">
|
||||
8. Revisions
|
||||
</h2>
|
||||
<p className="text-slate-600 dark:text-slate-300 leading-relaxed">
|
||||
{SITE_CONFIG.title} may revise these terms of service at any time without notice. By using this service, you are agreeing to be bound by the then current version of these terms of service.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 className="text-xl font-semibold text-slate-800 dark:text-white mb-4">
|
||||
9. Contact Information
|
||||
</h2>
|
||||
<p className="text-slate-600 dark:text-slate-300 leading-relaxed">
|
||||
If you have any questions about these Terms of Service, please contact us at{' '}
|
||||
<a href="mailto:dewe.developer@gmail.com" className="text-blue-600 hover:text-blue-700 dark:text-blue-400 dark:hover:text-blue-300 underline">
|
||||
dewe.developer@gmail.com
|
||||
</a>
|
||||
{' '}or through our website at {SITE_CONFIG.domain}.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Footer */}
|
||||
<div className="mt-8 text-center">
|
||||
<p className="text-sm text-slate-500 dark:text-slate-400">
|
||||
© {SITE_CONFIG.year} {SITE_CONFIG.title} • Built with ❤️ for developers worldwide
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default TermsOfService;
|
||||
Reference in New Issue
Block a user