diff --git a/components/domain-checker.tsx b/components/domain-checker.tsx new file mode 100644 index 0000000..fb28880 --- /dev/null +++ b/components/domain-checker.tsx @@ -0,0 +1,182 @@ +'use client'; + +import { useState, useEffect } from 'react'; +import { CheckCircle2, XCircle, AlertCircle, Loader2, Globe, ExternalLink } from 'lucide-react'; +import { cn } from '@/lib/utils'; +import { Button } from '@/components/ui/button'; +import { motion, AnimatePresence } from 'framer-motion'; + +interface DomainResult { + domain: string; + available: boolean; + error?: string; +} + +interface DomainCheckerProps { + results?: DomainResult[]; + loading?: boolean; +} + +export function DomainChecker({ results = [], loading = false }: DomainCheckerProps) { + const [animatedResults, setAnimatedResults] = useState([]); + + useEffect(() => { + if (results.length > 0) { + setAnimatedResults([]); + const timer = setTimeout(() => { + results.forEach((result, index) => { + setTimeout(() => { + setAnimatedResults(prev => [...prev, result]); + }, index * 100); + }); + }, 100); + return () => clearTimeout(timer); + } + }, [results]); + + if (loading) { + return ( +
+
+ +

Checking domain availability...

+
+
+ ); + } + + if (results.length === 0) { + return null; + } + + const availableCount = results.filter(r => r.available).length; + const takenCount = results.filter(r => !r.available && !r.error).length; + + return ( +
+
+ +

Domain Availability Check

+
+ + {availableCount > 0 || takenCount > 0 ? ( +
+
+
+ + {availableCount} available + +
+
+
+ + {takenCount} taken + +
+
+ ) : null} + +
+ + {animatedResults.map((result, index) => ( + + + + ))} + +
+
+ ); +} + +function DomainCard({ result }: { result: DomainResult }) { + const [isHovered, setIsHovered] = useState(false); + + if (result.error) { + return ( +
+
+
+ +
+

{result.domain}

+

{result.error}

+
+
+
+
+ ); + } + + const isAvailable = result.available; + + return ( +
setIsHovered(true)} + onMouseLeave={() => setIsHovered(false)} + > +
+
+
+ {isAvailable ? ( + + ) : ( + + )} +
+

{result.domain}

+

+ {isAvailable ? "Available for registration" : "Already registered"} +

+
+
+ + {isAvailable && ( + + + + )} +
+
+ + {isAvailable && ( + + )} +
+ ); +} \ No newline at end of file diff --git a/components/elements/context.tsx b/components/elements/context.tsx index 014715c..72ea552 100644 --- a/components/elements/context.tsx +++ b/components/elements/context.tsx @@ -156,7 +156,7 @@ function InfoRow({ costText?: string; }) { return ( -
+
{label}
@@ -275,20 +275,20 @@ export const Context = ({ - +
{displayPct} @@ -332,7 +332,7 @@ export const Context = ({ {costText && ( <> -
+
Total cost {costText}
@@ -343,4 +343,4 @@ export const Context = ({ ); -}; +}; \ No newline at end of file diff --git a/components/model-selector.tsx b/components/model-selector.tsx index 0a7426a..b3e9023 100644 --- a/components/model-selector.tsx +++ b/components/model-selector.tsx @@ -86,11 +86,11 @@ export function ModelSelector({ >