Hello! I am still unable to use the spacebar in the information fields of my shop. Everything is working almost perfectly
Spacebar will not work in information fields, I want it to work.
"use client"
import type React from "react"
import { useState, useEffect } from "react"
import Image from "next/image"
import { Plus, Minus, Copy, X, Trash2 } from "lucide-react"
interface Product {
id: string
name: string
price: number
image: string
description: string
sizes?: string[]
}
interface CartItem {
productId: string
size: string
quantity: number
}
const products: Product[] = [
{
id: "tshirt",
name: "AURA RACING T-SHIRT",
price: 1.5,
image: "/images/aura-racing-merch-display.jpeg",
description: "Premium quality t-shirt with AURA RACING branding.",
sizes: ["S", "M", "L", "XL"],
},
{
id: "hoodie",
name: "AURA RACING HOODIE",
price: 2.0,
image: "/images/aura-racing-hoodie.jpeg",
description: "Comfortable hoodie perfect for racing events.",
sizes: ["S", "M", "L", "XL"],
},
]
export default function SolanaShop() {
const [cart, setCart] = useState<CartItem[]>([])
const [showCart, setShowCart] = useState(false)
const [showCheckout, setShowCheckout] = useState(false)
useEffect(() => {
// Load cart from localStorage on component mount
try {
const savedCart = localStorage.getItem("aura-cart")
if (savedCart) {
setCart(JSON.parse(savedCart))
}
} catch (error) {
console.error("Error loading cart:", error)
}
// Listen for show cart events from navigation
const handleShowCart = () => {
setShowCart(true)
}
window.addEventListener("showCart", handleShowCart)
return () => {
window.removeEventListener("showCart", handleShowCart)
}
}, [])
// Save cart to localStorage whenever cart changes
useEffect(() => {
try {
localStorage.setItem("aura-cart", JSON.stringify(cart))
// Dispatch custom event to update cart button
window.dispatchEvent(new CustomEvent("cartUpdated"))
} catch (error) {
console.error("Error saving cart:", error)
}
}, [cart])
const addToCart = (productId: string, size: string) => {
const existingItem = cart.find((item) => item.productId === productId && item.size === size)
if (existingItem) {
setCart(
cart.map((item) =>
item.productId === productId && item.size === size ? { ...item, quantity: item.quantity + 1 } : item,
),
)
} else {
setCart([...cart, { productId, size, quantity: 1 }])
}
}
const updateQuantity = (productId: string, size: string, quantity: number) => {
if (quantity <= 0) {
setCart(cart.filter((item) => !(item.productId === productId && item.size === size)))
} else {
setCart(cart.map((item) => (item.productId === productId && item.size === size ? { ...item, quantity } : item)))
}
}
const removeFromCart = (productId: string, size: string) => {
setCart(cart.filter((item) => !(item.productId === productId && item.size === size)))
}
const getCartTotal = () => {
return cart.reduce((total, item) => {
const product = products.find((p) => p.id === item.productId)
return total + (product?.price || 0) * item.quantity
}, 0)
}
return (
<div className="w-full relative">
{/* Products Grid */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
{products.map((product) => (
<ProductCard key={product.id} product={product} onAddToCart={addToCart} />
))}
</div>
{/* Cart Modal */}
{showCart && (
<div className="fixed inset-0 bg-black/80 flex items-center justify-center z-50 p-4">
<div className="bg-black border border-gray-700 rounded-lg p-6 w-full max-w-md max-h-[80vh] overflow-y-auto">
<div className="flex items-center justify-between mb-4">
<h2 className="text-lg font-bold text-white">Your Cart</h2>
<button onClick={() => setShowCart(false)} className="text-gray-400 hover:text-white">
<X size={20} />
</button>
</div>
{cart.length === 0 ? (
<div className="text-center py-6">
<p className="text-gray-400 mb-4">Your cart is empty</p>
<button onClick={() => setShowCart(false)} className="btn-secondary">
Continue Shopping
</button>
</div>
) : (
<>
<div className="space-y-4 mb-6">
{cart.map((item, index) => {
const product = products.find((p) => p.id === item.productId)
if (!product) return null
return (
<div key={index} className="flex items-center space-x-4 p-3 bg-gray-800 rounded">
<div className="w-12 h-12 relative">
<Image
src={product.image || "/placeholder.svg"}
alt={product.name}
fill
className="object-cover rounded"
sizes="48px"
/>
</div>
<div className="flex-1">
<h4 className="font-semibold text-white text-sm">{product.name}</h4>
<p className="text-xs text-gray-400">Size: {item.size}</p>
<div className="flex items-center mt-1">
<button
onClick={() => updateQuantity(item.productId, item.size, item.quantity - 1)}
className="bg-gray-700 hover:bg-gray-600 text-white rounded-l p-1"
>
<Minus size={14} />
</button>
<span className="bg-gray-700 text-white px-3 py-1 text-xs">{item.quantity}</span>
<button
onClick={() => updateQuantity(item.productId, item.size, item.quantity + 1)}
className="bg-gray-700 hover:bg-gray-600 text-white rounded-r p-1"
>
<Plus size={14} />
</button>
<span className="ml-2 text-sm text-white">
{(product.price * item.quantity).toFixed(2)} SOL
</span>
</div>
</div>
<button
onClick={() => removeFromCart(item.productId, item.size)}
className="text-red-400 hover:text-red-300"
>
<Trash2 size={16} />
</button>
</div>
)
})}
</div>
<div className="border-t border-gray-700 pt-4 mb-6">
<div className="flex items-center justify-between text-lg font-bold text-white">
<span>Total:</span>
<span>{getCartTotal().toFixed(2)} SOL</span>
</div>
</div>
<button
onClick={() => {
setShowCart(false)
setShowCheckout(true)
}}
className="btn-primary w-full"
>
CHECKOUT
</button>
</>
)}
</div>
</div>
)}
{/* Checkout Modal */}
{showCheckout && (
<CheckoutModal
cart={cart}
products={products}
total={getCartTotal()}
onClose={() => setShowCheckout(false)}
onComplete={() => {
setCart([])
setShowCart(false)
setShowCheckout(false)
}}
/>
)}
</div>
)
}
function ProductCard({ product, onAddToCart }: { product: Product; onAddToCart: (id: string, size: string) => void }) {
const [selectedSize, setSelectedSize] = useState(product.sizes?.[0] || "")
return (
<div className="bg-black/40 border border-gray-700 rounded-lg p-6 backdrop-blur-sm">
<div className="w-full h-64 relative mb-4 rounded-lg overflow-hidden">
<Image
src={product.image || "/placeholder.svg"}
alt={product.name}
fill
className="object-cover"
sizes="(max-width: 768px) 100vw, 50vw"
/>
</div>
<h3 className="text-lg font-bold text-white mb-2">{product.name}</h3>
<p className="text-sm text-gray-300 mb-4">{product.description}</p>
{product.sizes && product.sizes.length > 0 && (
<div className="mb-4 text-center">
<h4 className="text-sm font-semibold text-white mb-2">SIZE</h4>
<div className="flex justify-center space-x-2">
{product.sizes.map((size) => (
<button
key={size}
onClick={() => setSelectedSize(size)}
className={`px-3 py-1 text-sm rounded border ${
selectedSize === size
? "border-purple-500 bg-purple-500/20 text-purple-400"
: "border-gray-600 text-gray-300"
}`}
>
{size}
</button>
))}
</div>
</div>
)}
<div className="flex items-center justify-center text-2xl mb-4">
<span className="mr-2 text-white font-bold">{product.price}</span>
<Image src="/images/solana-logo-clean.png" alt="Solana" width={24} height={24} />
</div>
<button
onClick={() => onAddToCart(product.id, selectedSize)}
className="btn-primary w-full flex items-center justify-center"
disabled={!selectedSize && !!product.sizes?.length}
>
<Plus size={16} className="mr-2" />
ADD TO CART
</button>
</div>
)
}
function CheckoutModal({
cart,
products,
total,
onClose,
onComplete,
}: {
cart: CartItem[]
products: Product[]
total: number
onClose: () => void
onComplete: () => void
}) {
const [step, setStep] = useState<"info" | "payment" | "confirmation">("info")
const [copied, setCopied] = useState(false)
const [emailStatus, setEmailStatus] = useState<"idle" | "sending" | "success" | "error">("idle")
const [customerInfo, setCustomerInfo] = useState({
name: "",
email: "",
address: "",
city: "",
zipCode: "",
country: "",
phone: "",
})
const walletAddress = "gVgoRfDUECsHCQyFxPusyEHENcQmeXNqchYHyDQ9bqw"
const copyAddress = () => {
navigator.clipboard.writeText(walletAddress)
setCopied(true)
setTimeout(() => setCopied(false), 2000)
}
const handleInfoSubmit = (e: React.FormEvent) => {
e.preventDefault()
setStep("payment")
}
const handleOrderSubmit = () => {
// Generate unique order ID
const orderId = `ARP-${Date.now().toString().slice(-8)}`
// Create order object
const order = {
id: orderId,
timestamp: new Date().toISOString(),
customerInfo,
items: cart.map((item) => {
const product = products.find((p) => p.id === item.productId)
return {
productId: item.productId,
productName: product?.name || "Unknown Product",
size: item.size,
quantity: item.quantity,
price: product?.price || 0,
}
}),
total,
paymentAddress: walletAddress,
status: "pending" as const,
}
// Save order to localStorage
try {
const existingOrders = JSON.parse(localStorage.getItem("aura-orders") || "[]")
const updatedOrders = [order, ...existingOrders]
localStorage.setItem("aura-orders", JSON.stringify(updatedOrders))
localStorage.setItem("aura-latest-order", JSON.stringify(order))
console.log("Order saved:", order)
// Send notification via Resend API
sendOrderNotification(order)
} catch (error) {
console.error("Error saving order:", error)
}
setStep("confirmation")
}
// Send order notification via Resend API
const sendOrderNotification = async (order: any) => {
setEmailStatus("sending")
console.log("🔄 Sending order notification via Resend API...")
try {
const response = await fetch("/api/send-order-notification", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ order }),
})
if (response.ok) {
console.log("âś… Resend notification sent successfully!")
setEmailStatus("success")
} else {
console.error("❌ Resend API failed:", await response.text())
setEmailStatus("error")
}
} catch (error) {
console.error("❌ Network error:", error)
setEmailStatus("error")
}
}
if (step === "confirmation") {
return (
<div className="fixed inset-0 bg-black/80 flex items-center justify-center z-50 p-4">
<div className="bg-black border border-gray-700 rounded-lg p-6 w-full max-w-md text-center">
<div className="w-16 h-16 bg-green-500 rounded-full flex items-center justify-center mx-auto mb-4">
<svg className="w-8 h-8 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
</svg>
</div>
<h2 className="text-xl font-bold text-green-500 mb-4">Order Submitted!</h2>
{/* Email Status */}
<div className="mb-4">
{emailStatus === "sending" && (
<div className="bg-blue-500/10 border border-blue-500/30 rounded-lg p-3">
<p className="text-blue-400 text-sm">đź“§ Sending notification via Resend...</p>
</div>
)}
{emailStatus === "success" && (
<div className="bg-green-500/10 border border-green-500/30 rounded-lg p-3">
<p className="text-green-400 text-sm">âś… Professional email notification sent!</p>
</div>
)}
{/* Removed the "Email service unavailable" warning as per user request */}
</div>
<div className="bg-gray-800 p-4 rounded-lg mb-4">
<p className="text-gray-300 mb-2">
Thank you for your order! We've received your order details and will process it once payment is confirmed.
</p>
<div className="text-sm text-gray-400">
<p>
<strong>Order ID:</strong> {JSON.parse(localStorage.getItem("aura-latest-order") || "{}")?.id || "N/A"}
</p>
<p>
<strong>Email:</strong> {customerInfo.email}
</p>
</div>
</div>
<div className="bg-blue-500/10 border border-blue-500/30 rounded-lg p-3 mb-4">
<p className="text-blue-400 text-sm">
You'll receive a confirmation email once we verify your payment. Shipping typically takes 5-10 business
days.
</p>
</div>
<button onClick={onComplete} className="btn-primary w-full">
CONTINUE SHOPPING
</button>
</div>
</div>
)
}
return (
<div className="fixed inset-0 bg-black/80 flex items-center justify-center z-50 p-4">
<div className="bg-black border border-gray-700 rounded-lg p-6 w-full max-w-2xl max-h-[90vh] overflow-y-auto">
<div className="flex items-center justify-between mb-6">
<h2 className="text-xl font-bold text-white">
{step === "info" && "Shipping Information"}
{step === "payment" && "Payment"}
</h2>
<button onClick={onClose} className="text-gray-400 hover:text-white text-2xl">
<X size={24} />
</button>
</div>
{step === "info" && (
<form onSubmit={handleInfoSubmit} className="space-y-6">
{/* Order Summary */}
<div className="bg-gray-800 p-4 rounded-lg">
<h3 className="text-lg font-bold mb-4 text-white">Order Summary</h3>
{cart.map((item, index) => {
const product = products.find((p) => p.id === item.productId)
if (!product) return null
return (
<div
key={index}
className="flex justify-between items-center py-2 border-b border-gray-700 last:border-b-0"
>
<div>
<p className="font-medium text-white">{product.name}</p>
<p className="text-sm text-gray-400">
Size: {item.size} | Qty: {item.quantity}
</p>
</div>
<div className="flex items-center">
<span className="mr-2 text-white">{(product.price * item.quantity).toFixed(2)}</span>
<Image src="/images/solana-logo-clean.png" alt="SOL" width={16} height={16} />
</div>
</div>
)
})}
<div className="flex justify-between items-center pt-4 text-lg font-bold text-white">
<span>Total:</span>
<div className="flex items-center">
<span className="mr-2">{total.toFixed(2)}</span>
<Image src="/images/solana-logo-clean.png" alt="SOL" width={20} height={20} />
</div>
</div>
</div>
{/* Customer Information Form */}
<div className="bg-gray-800 p-4 rounded-lg">
<h3 className="text-lg font-bold mb-4 text-white">Shipping Information</h3>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div className="md:col-span-2">
<label className="block text-sm font-medium text-gray-300 mb-2">Full Name *</label>
<input
type="text"
value={customerInfo.name}
onChange={(e) => setCustomerInfo({ ...customerInfo, name: e.target.value })}
className="w-full p-3 bg-gray-700 border border-gray-600 rounded text-white focus:outline-none focus:border-purple-500"
required
placeholder="John Doe"
/>
</div>
<div className="md:col-span-2">
<label className="block text-sm font-medium text-gray-300 mb-2">Email Address *</label>
<input
type="email"
value={customerInfo.email}
onChange={(e) => setCustomerInfo({ ...customerInfo, email: e.target.value })}
className="w-full p-3 bg-gray-700 border border-gray-600 rounded text-white focus:outline-none focus:border-purple-500"
required
placeholder="john@example.com"
/>
</div>
<div className="md:col-span-2">
<label className="block text-sm font-medium text-gray-300 mb-2">Street Address *</label>
<input
type="text"
value={customerInfo.address}
onChange={(e) => setCustomerInfo({ ...customerInfo, address: e.target.value })}
className="w-full p-3 bg-gray-700 border border-gray-600 rounded text-white focus:outline-none focus:border-purple-500"
required
placeholder="123 Main Street, Apt 4B"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-300 mb-2">City *</label>
<input
type="text"
value={customerInfo.city}
onChange={(e) => setCustomerInfo({ ...customerInfo, city: e.target.value })}
className="w-full p-3 bg-gray-700 border border-gray-600 rounded text-white focus:outline-none focus:border-purple-500"
required
placeholder="New York"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-300 mb-2">ZIP/Postal Code *</label>
<input
type="text"
value={customerInfo.zipCode}
onChange={(e) => setCustomerInfo({ ...customerInfo, zipCode: e.target.value })}
className="w-full p-3 bg-gray-700 border border-gray-600 rounded text-white focus:outline-none focus:border-purple-500"
required
placeholder="10001"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-300 mb-2">Country *</label>
<input
type="text"
value={customerInfo.country}
onChange={(e) => setCustomerInfo({ ...customerInfo, country: e.target.value })}
className="w-full p-3 bg-gray-700 border border-gray-600 rounded text-white focus:outline-none focus:border-purple-500"
required
placeholder="United States"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-300 mb-2">Phone Number (Optional)</label>
<input
type="tel"
value={customerInfo.phone}
onChange={(e) => setCustomerInfo({ ...customerInfo, phone: e.target.value })}
className="w-full p-3 bg-gray-700 border border-gray-600 rounded text-white focus:outline-none focus:border-purple-500"
placeholder="+1 (555) 123-4567"
/>
</div>
</div>
</div>
<button type="submit" className="btn-primary w-full">
PROCEED TO PAYMENT
</button>
</form>
)}
{step === "payment" && (
<div className="space-y-6">
{/* Customer Info Review */}
<div className="bg-gray-800 p-4 rounded-lg">
<h3 className="text-lg font-bold mb-3 text-white">Shipping To:</h3>
<div className="text-sm text-gray-300">
<p className="font-medium text-white">{customerInfo.name}</p>
<p>{customerInfo.address}</p>
<p>
{customerInfo.city}, {customerInfo.zipCode}
</p>
<p>{customerInfo.country}</p>
<p className="mt-2 text-gray-400">{customerInfo.email}</p>
{customerInfo.phone && <p className="text-gray-400">{customerInfo.phone}</p>}
</div>
</div>
{/* Payment Instructions */}
<div className="bg-gray-800 p-4 rounded-lg">
<h3 className="text-lg font-bold mb-4 text-white">Payment Instructions</h3>
<div className="space-y-4">
<div className="flex items-center space-x-2 text-yellow-400">
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L3.732 16.5c-.77.833.192 2.5 1.732 2.5z"
/>
</svg>
<span className="text-sm">Send exactly {total.toFixed(6)} SOL to the address below</span>
</div>
<div className="bg-gray-700 p-3 rounded">
<p className="text-xs break-all font-mono text-white">{walletAddress}</p>
</div>
<button onClick={copyAddress} className="btn-secondary w-full flex items-center justify-center">
<Copy size={16} className="mr-2" />
{copied ? "Copied!" : "Copy Address"}
</button>
<div className="bg-blue-500/10 border border-blue-500/30 rounded-lg p-4">
<p className="text-blue-400 text-sm">
<strong>Important:</strong> After sending payment, click "I've Sent Payment" below. We'll verify the
transaction and process your order within 24 hours.
</p>
</div>
</div>
</div>
<div className="flex space-x-4">
<button onClick={() => setStep("info")} className="btn-secondary flex-1">
BACK
</button>
<button onClick={handleOrderSubmit} className="btn-primary flex-1">
I'VE SENT PAYMENT
</button>
</div>
</div>
)}
</div>
</div>
)
}
I just want to be able to type normally in the information fields.