Merge version_2 into main #2

Merged
bender merged 2 commits from version_2 into main 2026-03-04 16:08:58 +00:00
2 changed files with 224 additions and 40 deletions

View File

@@ -1,55 +1,45 @@
import type { Metadata } from "next";
import { Halant } from "next/font/google";
import { Inter } from "next/font/google";
import { Raleway } from "next/font/google";
import "./globals.css";
import { ServiceWrapper } from "@/components/ServiceWrapper";
import Tag from "@/tag/Tag";
const halant = Halant({
variable: "--font-halant", subsets: ["latin"],
weight: ["300", "400", "500", "600", "700"],
});
const inter = Inter({
variable: "--font-inter", subsets: ["latin"],
});
const raleway = Raleway({
variable: "--font-raleway", subsets: ["latin"],
});
export const metadata: Metadata = {
title: "Dataset Cleaner - Privacy-First Data Cleaning Tool", description: "Clean, validate, and transform your datasets with Dataset Cleaner. 100% browser-based, no data leaves your computer. Remove duplicates, trim whitespace, handle special characters with AI-powered precision.", keywords: "data cleaning, data validation, dataset tool, CSV cleaner, data quality, AI cleaning, browser-based", metadataBase: new URL("https://datasetcleaner.com"),
alternates: {
canonical: "https://datasetcleaner.com"},
canonical: "https://datasetcleaner.com"
},
openGraph: {
title: "Dataset Cleaner - Privacy-First Data Cleaning Tool", description: "Clean your datasets with confidence. 100% private, browser-based data cleaning powered by AI.", url: "https://datasetcleaner.com", siteName: "Dataset Cleaner", type: "website", images: [
{
url: "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3AUGg4tVcwa1xJbmjLxOEngSK3W/a-modern-professional-software-dashboard-1772640055925-4dba2f06.png", alt: "Dataset Cleaner Dashboard"},
],
url: "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3AUGg4tVcwa1xJbmjLxOEngSK3W/a-modern-professional-software-dashboard-1772640055925-4dba2f06.png", alt: "Dataset Cleaner Dashboard"
}
]
},
twitter: {
card: "summary_large_image", title: "Dataset Cleaner - Privacy-First Data Cleaning", description: "Clean your datasets with confidence. 100% private, browser-based data cleaning powered by AI.", images: [
"https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3AUGg4tVcwa1xJbmjLxOEngSK3W/a-modern-professional-software-dashboard-1772640055925-4dba2f06.png"],
"https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3AUGg4tVcwa1xJbmjLxOEngSK3W/a-modern-professional-software-dashboard-1772640055925-4dba2f06.png"
]
},
robots: {
index: true,
follow: true,
},
follow: true
}
};
export default function RootLayout({
children,
children
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en" suppressHydrationWarning>
<ServiceWrapper>
<body
className={`${halant.variable} ${inter.variable} ${raleway.variable} antialiased`}
>
<body className={`${inter.variable} antialiased`}>
<Tag />
{children}

View File

@@ -1,5 +1,6 @@
"use client"
import { useState } from "react";
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
import NavbarStyleFullscreen from '@/components/navbar/NavbarStyleFullscreen/NavbarStyleFullscreen';
import HeroBillboardGallery from '@/components/sections/hero/HeroBillboardGallery';
@@ -7,9 +8,62 @@ import FeatureCardTwentyOne from '@/components/sections/feature/FeatureCardTwent
import ContactSplitForm from '@/components/sections/contact/ContactSplitForm';
import TestimonialCardThirteen from '@/components/sections/testimonial/TestimonialCardThirteen';
import FooterMedia from '@/components/sections/footer/FooterMedia';
import { Shield, Sparkles, Star } from 'lucide-react';
import { Shield, Sparkles, Star, Upload, Download, Zap, Lock, RefreshCw, AlertCircle } from 'lucide-react';
export default function LandingPage() {
const [tokenValue, setTokenValue] = useState("");
const [datasetId, setDatasetId] = useState("");
const [verificationStatus, setVerificationStatus] = useState<"idle" | "verified" | "invalid">("idle");
const [cleaningProgress, setCleaningProgress] = useState(0);
const [selectedCleaningOptions, setSelectedCleaningOptions] = useState<string[]>([]);
const [isProcessing, setIsProcessing] = useState(false);
const handleTokenVerification = () => {
if (tokenValue && tokenValue.length >= 8) {
setVerificationStatus("verified");
} else {
setVerificationStatus("invalid");
}
};
const handleDatasetFetch = () => {
if (datasetId && verificationStatus === "verified") {
// Simulate dataset fetch
console.log("Fetching dataset:", datasetId);
}
};
const handleCleaningOptionToggle = (option: string) => {
setSelectedCleaningOptions(prev =>
prev.includes(option)
? prev.filter(o => o !== option)
: [...prev, option]
);
};
const handleStartCleaning = () => {
if (selectedCleaningOptions.length === 0) return;
setIsProcessing(true);
setCleaningProgress(0);
// Simulate cleaning pipeline with progress tracking
const interval = setInterval(() => {
setCleaningProgress(prev => {
if (prev >= 100) {
clearInterval(interval);
setIsProcessing(false);
return 100;
}
return prev + Math.random() * 30;
});
}, 500);
};
const handleDownloadOutput = () => {
console.log("Downloading cleaned dataset...");
};
return (
<ThemeProvider
defaultButtonVariant="icon-arrow"
@@ -30,7 +84,6 @@ export default function LandingPage() {
{ name: "Features", id: "features" },
{ name: "App", id: "app" },
{ name: "Documentation", id: "docs" },
{ name: "Pricing", id: "pricing" },
{ name: "Contact", id: "contact" }
]}
bottomLeftText="Privacy First — No data leaves your browser"
@@ -93,22 +146,163 @@ export default function LandingPage() {
</div>
<div id="app" data-section="app">
<ContactSplitForm
title="Start Cleaning Your Data"
description="Upload your dataset or paste data directly. Our tool processes everything locally in your browser for maximum privacy and security."
inputs={[
{ name: "email", type: "email", placeholder: "your@email.com", required: true },
{ name: "datasetName", type: "text", placeholder: "My Dataset Name", required: true }
]}
textarea={{ name: "dataDescription", placeholder: "Describe your dataset and cleaning needs...", rows: 5, required: false }}
imageSrc="https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3AUGg4tVcwa1xJbmjLxOEngSK3W/uploaded-1772640003528-ovou18nk.png?_wi=2"
imageAlt="Dataset Cleaner Application"
useInvertedBackground={true}
mediaPosition="right"
mediaAnimation="slide-up"
buttonText="Start Cleaning"
containerClassName="py-20"
/>
<div className="w-full py-20 px-6">
<div className="max-w-6xl mx-auto">
{/* Token Integration Section */}
<div className="mb-12 p-8 bg-white rounded-2xl shadow-lg border border-gray-200">
<div className="flex items-center gap-3 mb-6">
<Lock className="w-6 h-6 text-blue-600" />
<h2 className="text-2xl font-semibold">Token Verification & Integration</h2>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 mb-6">
<div>
<label className="block text-sm font-medium mb-2">API Token</label>
<input
type="password"
value={tokenValue}
onChange={(e) => setTokenValue(e.target.value)}
placeholder="Enter your API token"
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
/>
</div>
<div>
<label className="block text-sm font-medium mb-2">Dataset ID</label>
<input
type="text"
value={datasetId}
onChange={(e) => setDatasetId(e.target.value)}
placeholder="Enter dataset ID"
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
/>
</div>
</div>
<div className="flex gap-4">
<button
onClick={handleTokenVerification}
className="px-6 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition flex items-center gap-2"
>
<AlertCircle className="w-4 h-4" />
Verify Token
</button>
<button
onClick={handleDatasetFetch}
disabled={verificationStatus !== "verified"}
className="px-6 py-2 bg-green-600 text-white rounded-lg hover:bg-green-700 transition disabled:opacity-50 disabled:cursor-not-allowed flex items-center gap-2"
>
<Upload className="w-4 h-4" />
Fetch Dataset
</button>
</div>
{verificationStatus === "verified" && (
<div className="mt-4 p-3 bg-green-50 text-green-700 rounded-lg flex items-center gap-2">
<Sparkles className="w-4 h-4" />
Token verified successfully!
</div>
)}
{verificationStatus === "invalid" && (
<div className="mt-4 p-3 bg-red-50 text-red-700 rounded-lg flex items-center gap-2">
<AlertCircle className="w-4 h-4" />
Invalid token or insufficient length
</div>
)}
</div>
{/* Cleaning Options Section */}
<div className="mb-12 p-8 bg-white rounded-2xl shadow-lg border border-gray-200">
<div className="flex items-center gap-3 mb-6">
<Zap className="w-6 h-6 text-orange-500" />
<h2 className="text-2xl font-semibold">Cleaning Pipeline Configuration</h2>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 mb-6">
{[
{ id: "duplicates", label: "Remove Duplicates", icon: RefreshCw },
{ id: "whitespace", label: "Whitespace Normalization", icon: Zap },
{ id: "repeated", label: "Remove Repeated Values", icon: RefreshCw },
{ id: "special", label: "Special Characters Removal", icon: AlertCircle },
{ id: "formatting", label: "Format Standardization", icon: Zap },
{ id: "encoding", label: "Character Encoding Fix", icon: Zap }
].map(option => {
const IconComponent = option.icon;
return (
<label key={option.id} className="flex items-center gap-3 p-4 border border-gray-200 rounded-lg hover:bg-gray-50 cursor-pointer transition">
<input
type="checkbox"
checked={selectedCleaningOptions.includes(option.id)}
onChange={() => handleCleaningOptionToggle(option.id)}
className="w-4 h-4 text-blue-600 rounded"
/>
<IconComponent className="w-4 h-4 text-gray-600" />
<span className="text-sm font-medium">{option.label}</span>
</label>
);
})}
</div>
<button
onClick={handleStartCleaning}
disabled={selectedCleaningOptions.length === 0 || isProcessing}
className="w-full px-6 py-3 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center gap-2 font-semibold"
>
<Zap className="w-5 h-5" />
{isProcessing ? "Processing..." : "Start Cleaning Pipeline"}
</button>
</div>
{/* Progress Tracking Section */}
{isProcessing && (
<div className="mb-12 p-8 bg-white rounded-2xl shadow-lg border border-gray-200">
<div className="flex items-center gap-3 mb-6">
<RefreshCw className="w-6 h-6 text-blue-600 animate-spin" />
<h2 className="text-2xl font-semibold">Cleaning Progress</h2>
</div>
<div className="space-y-4">
<div>
<div className="flex justify-between mb-2">
<span className="text-sm font-medium">Overall Progress</span>
<span className="text-sm font-medium">{Math.round(cleaningProgress)}%</span>
</div>
<div className="w-full bg-gray-200 rounded-full h-3 overflow-hidden">
<div
className="bg-gradient-to-r from-blue-500 to-blue-600 h-full transition-all duration-300"
style={{ width: `${cleaningProgress}%` }}
/>
</div>
</div>
<div className="grid grid-cols-2 md:grid-cols-3 gap-4 text-sm">
{selectedCleaningOptions.map(option => (
<div key={option} className="p-3 bg-blue-50 rounded-lg">
<div className="font-medium text-gray-700 capitalize">{option.replace(/([A-Z])/g, ' $1').trim()}</div>
<div className="text-gray-500 text-xs">In progress...</div>
</div>
))}
</div>
</div>
</div>
)}
{/* Download Section */}
{cleaningProgress === 100 && (
<div className="p-8 bg-white rounded-2xl shadow-lg border border-green-200">
<div className="flex items-center gap-3 mb-6">
<Download className="w-6 h-6 text-green-600" />
<h2 className="text-2xl font-semibold">Download Cleaned Dataset</h2>
</div>
<p className="text-gray-600 mb-6">Your dataset has been successfully cleaned! Choose your preferred format to download.</p>
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
{["CSV", "XLSX", "JSON", "XML"].map(format => (
<button
key={format}
onClick={handleDownloadOutput}
className="px-4 py-3 bg-green-600 text-white rounded-lg hover:bg-green-700 transition font-semibold flex items-center justify-center gap-2"
>
<Download className="w-4 h-4" />
{format}
</button>
))}
</div>
</div>
)}
</div>
</div>
</div>
<div id="testimonials" data-section="testimonials">
@@ -139,7 +333,7 @@ export default function LandingPage() {
logoText="Dataset Cleaner"
copyrightText="© 2025 Dataset Cleaner. All rights reserved."
columns={[
{ title: "Product", items: [{ label: "Features", href: "#features" }, { label: "Pricing", href: "#pricing" }, { label: "Documentation", href: "https://docs.datasetcleaner.com" }, { label: "API Reference", href: "https://api.datasetcleaner.com" }] },
{ title: "Product", items: [{ label: "Features", href: "#features" }, { label: "Documentation", href: "#docs" }, { label: "API Reference", href: "https://api.datasetcleaner.com" }, { label: "Status", href: "https://status.datasetcleaner.com" }] },
{ title: "Company", items: [{ label: "About Us", href: "#about" }, { label: "Blog", href: "https://blog.datasetcleaner.com" }, { label: "Careers", href: "#careers" }, { label: "Contact", href: "#contact" }] },
{ title: "Legal", items: [{ label: "Privacy Policy", href: "#privacy" }, { label: "Terms of Service", href: "#terms" }, { label: "Cookie Policy", href: "#cookies" }, { label: "Security", href: "https://security.datasetcleaner.com" }] }
]}