"use client"; import { useState, useCallback } from "react"; import { motion } from "framer-motion"; import { Image as ImageIcon, Zap } from "lucide-react"; import { FileUploader } from "@/components/tools/FileUploader"; import { ProgressBar } from "@/components/tools/ProgressBar"; import { ResultPreview } from "@/components/tools/ResultPreview"; import { ConfigPanel, type ConfigOption } from "@/components/tools/ConfigPanel"; import { Button } from "@/components/ui/button"; import { useUploadStore } from "@/store/uploadStore"; import { generateId } from "@/lib/utils"; import type { UploadedFile, ProcessedFile, ImageCompressConfig } from "@/types"; const imageAccept = { "image/*": [".png", ".jpg", ".jpeg", ".webp", ".gif", ".bmp"], }; const defaultConfig: ImageCompressConfig = { quality: 80, format: "original", }; const configOptions: ConfigOption[] = [ { id: "quality", type: "slider", label: "Compression Quality", description: "Lower quality = smaller file size", value: defaultConfig.quality, min: 1, max: 100, step: 1, suffix: "%", icon: , }, { id: "format", type: "select", label: "Output Format", description: "Convert to a different format (optional)", value: defaultConfig.format, options: [ { label: "Original", value: "original" }, { label: "JPEG", value: "jpeg" }, { label: "PNG", value: "png" }, { label: "WebP", value: "webp" }, ], }, ]; export default function ImageCompressPage() { const { files, addFile, removeFile, clearFiles, processingStatus, setProcessingStatus } = useUploadStore(); const [config, setConfig] = useState(defaultConfig); const [processedFiles, setProcessedFiles] = useState([]); const handleFilesDrop = useCallback( (acceptedFiles: File[]) => { const newFiles: UploadedFile[] = acceptedFiles.map((file) => ({ id: generateId(), file, name: file.name, size: file.size, type: file.type, uploadedAt: new Date(), })); newFiles.forEach((file) => addFile(file)); }, [addFile] ); const handleConfigChange = (id: string, value: any) => { setConfig((prev) => ({ ...prev, [id]: value })); }; const handleResetConfig = () => { setConfig(defaultConfig); }; const handleProcess = async () => { if (files.length === 0) return; setProcessingStatus({ status: "uploading", progress: 0, message: "Uploading images...", }); try { // Simulate upload for (let i = 0; i <= 100; i += 10) { await new Promise((resolve) => setTimeout(resolve, 50)); setProcessingStatus({ status: "uploading", progress: i, message: `Uploading... ${i}%`, }); } setProcessingStatus({ status: "processing", progress: 0, message: "Compressing images...", }); // Simulate processing for (let i = 0; i <= 100; i += 5) { await new Promise((resolve) => setTimeout(resolve, 100)); setProcessingStatus({ status: "processing", progress: i, message: `Compressing... ${i}%`, }); } // Simulate completion const results: ProcessedFile[] = files.map((file) => ({ id: generateId(), originalFile: file, processedUrl: "#", metadata: { format: config.format === "original" ? file.file.type.split("/")[1] : config.format, quality: config.quality, compressionRatio: Math.floor(Math.random() * 30) + 40, // Simulated 40-70% }, createdAt: new Date(), })); setProcessedFiles(results); clearFiles(); setProcessingStatus({ status: "completed", progress: 100, message: "Compression complete!", }); } catch (error) { setProcessingStatus({ status: "failed", progress: 0, message: "Compression failed", error: error instanceof Error ? error.message : "Unknown error", }); } }; const handleDownload = (fileId: string) => { console.log("Downloading file:", fileId); }; const canProcess = files.length > 0 && processingStatus.status !== "processing"; return (

Image Compression

Optimize images for web and mobile without quality loss

({ ...opt, value: config[opt.id as keyof ImageCompressConfig], }))} onChange={handleConfigChange} onReset={handleResetConfig} /> {canProcess && ( )}
{processingStatus.status !== "idle" && ( )} {processedFiles.length > 0 && ( )}

Features

  • • Batch processing - compress multiple images at once
  • • Smart compression - maintains visual quality
  • • Format conversion - PNG to JPEG, WebP, and more
  • • Up to 80% size reduction without quality loss
); }