"use client"; import { DashboardLayout } from "@/components/layout/sidebar"; import { PageHeader } from "@/components/layout/page-header"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Separator } from "@/components/ui/separator"; import { Calculator, Clock, Link2, ExternalLink, Github, Globe, Cloud, Database, Play, Square, RotateCcw, Copy, Check } from "lucide-react"; import { useState, useEffect, useCallback, useRef } from "react"; // ============================================================================ // Types // ============================================================================ interface QuickLink { id: string; name: string; url: string; icon: React.ReactNode; color: string; } // ============================================================================ // Constants // ============================================================================ const QUICK_LINKS: QuickLink[] = [ { id: "github", name: "GitHub", url: "https://github.com", icon: , color: "bg-slate-800" }, { id: "vercel", name: "Vercel", url: "https://vercel.com", icon: , color: "bg-black" }, { id: "supabase", name: "Supabase", url: "https://supabase.com", icon: , color: "bg-emerald-600" }, { id: "gantt", name: "Gantt Board", url: "https://gantt-board.vercel.app", icon: , color: "bg-blue-600" }, { id: "google", name: "Google", url: "https://google.com", icon: , color: "bg-red-500" }, ]; // ============================================================================ // Calculator Component // ============================================================================ function CalculatorTool() { const [display, setDisplay] = useState("0"); const [previousValue, setPreviousValue] = useState(null); const [operation, setOperation] = useState(null); const [waitingForOperand, setWaitingForOperand] = useState(false); const [copied, setCopied] = useState(false); const clear = useCallback(() => { setDisplay("0"); setPreviousValue(null); setOperation(null); setWaitingForOperand(false); }, []); const inputDigit = useCallback((digit: string) => { if (waitingForOperand) { setDisplay(digit); setWaitingForOperand(false); } else { setDisplay(display === "0" ? digit : display + digit); } }, [display, waitingForOperand]); const inputDecimal = useCallback(() => { if (waitingForOperand) { setDisplay("0."); setWaitingForOperand(false); } else if (display.indexOf(".") === -1) { setDisplay(display + "."); } }, [display, waitingForOperand]); const performOperation = useCallback((nextOperation: string) => { const inputValue = parseFloat(display); if (previousValue === null) { setPreviousValue(inputValue); } else if (operation) { const currentValue = previousValue || 0; const newValue = calculate(currentValue, inputValue, operation); setPreviousValue(newValue); setDisplay(String(newValue)); } setWaitingForOperand(true); setOperation(nextOperation); }, [display, operation, previousValue]); const calculate = (firstValue: number, secondValue: number, op: string): number => { switch (op) { case "+": return firstValue + secondValue; case "-": return firstValue - secondValue; case "×": return firstValue * secondValue; case "÷": return secondValue !== 0 ? firstValue / secondValue : 0; default: return secondValue; } }; const performCalculation = useCallback(() => { const inputValue = parseFloat(display); if (previousValue !== null && operation) { const newValue = calculate(previousValue, inputValue, operation); setDisplay(String(newValue)); setPreviousValue(null); setOperation(null); setWaitingForOperand(true); } }, [display, operation, previousValue]); const copyResult = useCallback(() => { navigator.clipboard.writeText(display); setCopied(true); setTimeout(() => setCopied(false), 1500); }, [display]); const buttons = [ { label: "C", onClick: clear, className: "bg-red-500/10 text-red-500 hover:bg-red-500/20" }, { label: "±", onClick: () => setDisplay(String(parseFloat(display) * -1)), className: "bg-muted" }, { label: "%", onClick: () => setDisplay(String(parseFloat(display) / 100)), className: "bg-muted" }, { label: "÷", onClick: () => performOperation("÷"), className: "bg-primary/10 text-primary" }, { label: "7", onClick: () => inputDigit("7") }, { label: "8", onClick: () => inputDigit("8") }, { label: "9", onClick: () => inputDigit("9") }, { label: "×", onClick: () => performOperation("×"), className: "bg-primary/10 text-primary" }, { label: "4", onClick: () => inputDigit("4") }, { label: "5", onClick: () => inputDigit("5") }, { label: "6", onClick: () => inputDigit("6") }, { label: "-", onClick: () => performOperation("-"), className: "bg-primary/10 text-primary" }, { label: "1", onClick: () => inputDigit("1") }, { label: "2", onClick: () => inputDigit("2") }, { label: "3", onClick: () => inputDigit("3") }, { label: "+", onClick: () => performOperation("+"), className: "bg-primary/10 text-primary" }, { label: "0", onClick: () => inputDigit("0"), className: "col-span-2" }, { label: ".", onClick: inputDecimal }, { label: "=", onClick: performCalculation, className: "bg-primary text-primary-foreground hover:bg-primary/90" }, ]; return ( Calculator
{display}
{operation && ( {previousValue} {operation} )}
{buttons.map((btn) => ( ))}
); } // ============================================================================ // Timer Component // ============================================================================ function TimerTool() { const [seconds, setSeconds] = useState(0); const [isRunning, setIsRunning] = useState(false); const intervalRef = useRef(null); useEffect(() => { return () => { if (intervalRef.current) { clearInterval(intervalRef.current); } }; }, []); const start = useCallback(() => { if (!isRunning) { setIsRunning(true); intervalRef.current = setInterval(() => { setSeconds((s) => s + 1); }, 1000); } }, [isRunning]); const stop = useCallback(() => { if (intervalRef.current) { clearInterval(intervalRef.current); intervalRef.current = null; } setIsRunning(false); }, []); const reset = useCallback(() => { stop(); setSeconds(0); }, [stop]); const formatTime = (totalSeconds: number) => { const hours = Math.floor(totalSeconds / 3600); const minutes = Math.floor((totalSeconds % 3600) / 60); const secs = totalSeconds % 60; return `${hours.toString().padStart(2, "0")}:${minutes.toString().padStart(2, "0")}:${secs.toString().padStart(2, "0")}`; }; return ( Timer
{formatTime(seconds)}
); } // ============================================================================ // Quick Links Component // ============================================================================ function QuickLinksTool() { const [customLinks, setCustomLinks] = useState([]); const [newLinkName, setNewLinkName] = useState(""); const [newLinkUrl, setNewLinkUrl] = useState(""); const addCustomLink = useCallback(() => { if (newLinkName && newLinkUrl) { const url = newLinkUrl.startsWith("http") ? newLinkUrl : `https://${newLinkUrl}`; setCustomLinks((prev) => [ ...prev, { id: Date.now().toString(), name: newLinkName, url, icon: , color: "bg-muted", }, ]); setNewLinkName(""); setNewLinkUrl(""); } }, [newLinkName, newLinkUrl]); const removeCustomLink = useCallback((id: string) => { setCustomLinks((prev) => prev.filter((link) => link.id !== id)); }, []); return ( Quick Links {/* Default Links */}
{QUICK_LINKS.map((link) => ( {link.icon} {link.name} ))}
{/* Custom Links */} {customLinks.length > 0 && (

Custom Links

{customLinks.map((link) => (
{link.icon} {link.name}
))}
)} {/* Add Custom Link */}

Add Custom Link

setNewLinkName(e.target.value)} className="flex-1" /> setNewLinkUrl(e.target.value)} className="flex-1" />
); } // ============================================================================ // Password Generator Component // ============================================================================ function PasswordGeneratorTool() { const [password, setPassword] = useState(""); const [length, setLength] = useState(16); const [includeUppercase, setIncludeUppercase] = useState(true); const [includeNumbers, setIncludeNumbers] = useState(true); const [includeSymbols, setIncludeSymbols] = useState(true); const [copied, setCopied] = useState(false); const generatePassword = useCallback(() => { const lowercase = "abcdefghijklmnopqrstuvwxyz"; const uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; const numbers = "0123456789"; const symbols = "!@#$%^&*()_+-=[]{}|;:,.<>?"; let chars = lowercase; if (includeUppercase) chars += uppercase; if (includeNumbers) chars += numbers; if (includeSymbols) chars += symbols; let result = ""; for (let i = 0; i < length; i++) { result += chars.charAt(Math.floor(Math.random() * chars.length)); } setPassword(result); }, [length, includeUppercase, includeNumbers, includeSymbols]); const copyPassword = useCallback(() => { if (password) { navigator.clipboard.writeText(password); setCopied(true); setTimeout(() => setCopied(false), 1500); } }, [password]); return ( Password Generator
Length: {length} setLength(Number(e.target.value))} className="w-24 sm:w-32" />
); } // ============================================================================ // Main Page // ============================================================================ export default function ToolsPage() { return (
); }