Add src/app/admin/products/edit/page.tsx
This commit is contained in:
335
src/app/admin/products/edit/page.tsx
Normal file
335
src/app/admin/products/edit/page.tsx
Normal file
@@ -0,0 +1,335 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
|
||||
import NavbarLayoutFloatingOverlay from '@/components/navbar/NavbarLayoutFloatingOverlay/NavbarLayoutFloatingOverlay';
|
||||
import FooterMedia from '@/components/sections/footer/FooterMedia';
|
||||
import { ArrowLeft, Save, X } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
|
||||
interface ProductFormData {
|
||||
id: string;
|
||||
brand: string;
|
||||
name: string;
|
||||
price: string;
|
||||
rating: number;
|
||||
reviewCount: string;
|
||||
imageSrc: string;
|
||||
imageAlt: string;
|
||||
description: string;
|
||||
sku: string;
|
||||
stock: number;
|
||||
category: string;
|
||||
}
|
||||
|
||||
const initialFormData: ProductFormData = {
|
||||
id: "1", brand: "TechVault", name: "Pro Wireless Earbuds", price: "$249.99", rating: 5,
|
||||
reviewCount: "2.8k", imageSrc: "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3AiptcO4QrzBpwIQbUIl2kal97h/a-premium-tech-gadget-product-shot-sleek-1773085532843-b5a0598a.png", imageAlt: "Premium wireless earbuds", description: "High-quality wireless earbuds with active noise cancellation and 24-hour battery life", sku: "TWE-PRO-001", stock: 245,
|
||||
category: "Audio"
|
||||
};
|
||||
|
||||
export default function EditProductPage() {
|
||||
const [formData, setFormData] = useState<ProductFormData>(initialFormData);
|
||||
const [isSaving, setIsSaving] = useState(false);
|
||||
|
||||
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>) => {
|
||||
const { name, value } = e.target;
|
||||
setFormData(prev => ({
|
||||
...prev,
|
||||
[name]: name === "rating" || name === "stock" ? parseInt(value) : value
|
||||
}));
|
||||
};
|
||||
|
||||
const handleSave = async () => {
|
||||
setIsSaving(true);
|
||||
try {
|
||||
// Simulate API call
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
console.log("Product saved:", formData);
|
||||
alert("Product updated successfully!");
|
||||
} finally {
|
||||
setIsSaving(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleReset = () => {
|
||||
setFormData(initialFormData);
|
||||
};
|
||||
|
||||
return (
|
||||
<ThemeProvider
|
||||
defaultButtonVariant="text-stagger"
|
||||
defaultTextAnimation="entrance-slide"
|
||||
borderRadius="soft"
|
||||
contentWidth="smallMedium"
|
||||
sizing="mediumLargeSizeLargeTitles"
|
||||
background="circleGradient"
|
||||
cardStyle="outline"
|
||||
primaryButtonStyle="primary-glow"
|
||||
secondaryButtonStyle="radial-glow"
|
||||
headingFontWeight="semibold"
|
||||
>
|
||||
<div id="nav" data-section="nav">
|
||||
<NavbarLayoutFloatingOverlay
|
||||
brandName="TechVault"
|
||||
navItems={[
|
||||
{ name: "Shop", id: "products" },
|
||||
{ name: "Features", id: "features" },
|
||||
{ name: "Pricing", id: "pricing" },
|
||||
{ name: "Support", id: "contact" },
|
||||
{ name: "Admin", id: "https://techvault.io/admin" }
|
||||
]}
|
||||
button={{ text: "Back to Home", href: "/" }}
|
||||
className="backdrop-blur-md bg-opacity-80"
|
||||
buttonClassName="bg-gradient-to-r from-[#80da9b] to-[#a8e8ba] text-black font-semibold"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="min-h-screen bg-background pt-20 pb-20">
|
||||
<div className="max-w-4xl mx-auto px-4">
|
||||
{/* Header */}
|
||||
<div className="mb-8">
|
||||
<Link href="/" className="inline-flex items-center gap-2 text-primary-cta hover:opacity-80 transition-opacity mb-6">
|
||||
<ArrowLeft size={20} />
|
||||
<span>Back to Home</span>
|
||||
</Link>
|
||||
<h1 className="text-4xl font-bold text-foreground mb-2">Edit Product</h1>
|
||||
<p className="text-foreground/70">Modify product details, pricing, and inventory information</p>
|
||||
</div>
|
||||
|
||||
{/* Form Container */}
|
||||
<div className="bg-card rounded-lg border border-accent/20 p-8 shadow-lg">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
|
||||
{/* Product Image Preview */}
|
||||
<div className="flex flex-col gap-4">
|
||||
<div className="aspect-square rounded-lg overflow-hidden bg-background border border-accent/20 flex items-center justify-center">
|
||||
<img
|
||||
src={formData.imageSrc}
|
||||
alt={formData.imageAlt}
|
||||
className="w-full h-full object-cover"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-foreground mb-2">Image URL</label>
|
||||
<input
|
||||
type="text"
|
||||
name="imageSrc"
|
||||
value={formData.imageSrc}
|
||||
onChange={handleInputChange}
|
||||
className="w-full px-4 py-2 border border-accent/20 rounded-lg bg-background text-foreground placeholder-foreground/50 focus:outline-none focus:ring-2 focus:ring-primary-cta"
|
||||
placeholder="https://..."
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Product Details Form */}
|
||||
<div className="flex flex-col gap-6">
|
||||
{/* Brand & Name */}
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-foreground mb-2">Brand</label>
|
||||
<input
|
||||
type="text"
|
||||
name="brand"
|
||||
value={formData.brand}
|
||||
onChange={handleInputChange}
|
||||
className="w-full px-4 py-2 border border-accent/20 rounded-lg bg-background text-foreground placeholder-foreground/50 focus:outline-none focus:ring-2 focus:ring-primary-cta"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-foreground mb-2">Product Name</label>
|
||||
<input
|
||||
type="text"
|
||||
name="name"
|
||||
value={formData.name}
|
||||
onChange={handleInputChange}
|
||||
className="w-full px-4 py-2 border border-accent/20 rounded-lg bg-background text-foreground placeholder-foreground/50 focus:outline-none focus:ring-2 focus:ring-primary-cta"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* SKU & Category */}
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-foreground mb-2">SKU</label>
|
||||
<input
|
||||
type="text"
|
||||
name="sku"
|
||||
value={formData.sku}
|
||||
onChange={handleInputChange}
|
||||
className="w-full px-4 py-2 border border-accent/20 rounded-lg bg-background text-foreground placeholder-foreground/50 focus:outline-none focus:ring-2 focus:ring-primary-cta"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-foreground mb-2">Category</label>
|
||||
<select
|
||||
name="category"
|
||||
value={formData.category}
|
||||
onChange={handleInputChange}
|
||||
className="w-full px-4 py-2 border border-accent/20 rounded-lg bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary-cta"
|
||||
>
|
||||
<option>Audio</option>
|
||||
<option>Wearables</option>
|
||||
<option>Chargers</option>
|
||||
<option>Accessories</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Pricing & Inventory Section */}
|
||||
<div className="mt-8 pt-8 border-t border-accent/20">
|
||||
<h2 className="text-2xl font-bold text-foreground mb-6">Pricing & Inventory</h2>
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-foreground mb-2">Price</label>
|
||||
<input
|
||||
type="text"
|
||||
name="price"
|
||||
value={formData.price}
|
||||
onChange={handleInputChange}
|
||||
className="w-full px-4 py-2 border border-accent/20 rounded-lg bg-background text-foreground placeholder-foreground/50 focus:outline-none focus:ring-2 focus:ring-primary-cta"
|
||||
placeholder="$0.00"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-foreground mb-2">Stock Quantity</label>
|
||||
<input
|
||||
type="number"
|
||||
name="stock"
|
||||
value={formData.stock}
|
||||
onChange={handleInputChange}
|
||||
className="w-full px-4 py-2 border border-accent/20 rounded-lg bg-background text-foreground placeholder-foreground/50 focus:outline-none focus:ring-2 focus:ring-primary-cta"
|
||||
min="0"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-foreground mb-2">Rating</label>
|
||||
<select
|
||||
name="rating"
|
||||
value={formData.rating}
|
||||
onChange={handleInputChange}
|
||||
className="w-full px-4 py-2 border border-accent/20 rounded-lg bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary-cta"
|
||||
>
|
||||
<option value="1">1 Star</option>
|
||||
<option value="2">2 Stars</option>
|
||||
<option value="3">3 Stars</option>
|
||||
<option value="4">4 Stars</option>
|
||||
<option value="5">5 Stars</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Description & Review Count */}
|
||||
<div className="mt-8 pt-8 border-t border-accent/20">
|
||||
<h2 className="text-2xl font-bold text-foreground mb-6">Additional Details</h2>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-foreground mb-2">Review Count</label>
|
||||
<input
|
||||
type="text"
|
||||
name="reviewCount"
|
||||
value={formData.reviewCount}
|
||||
onChange={handleInputChange}
|
||||
className="w-full px-4 py-2 border border-accent/20 rounded-lg bg-background text-foreground placeholder-foreground/50 focus:outline-none focus:ring-2 focus:ring-primary-cta"
|
||||
placeholder="e.g., 2.8k"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-semibold text-foreground mb-2">Image Alt Text</label>
|
||||
<input
|
||||
type="text"
|
||||
name="imageAlt"
|
||||
value={formData.imageAlt}
|
||||
onChange={handleInputChange}
|
||||
className="w-full px-4 py-2 border border-accent/20 rounded-lg bg-background text-foreground placeholder-foreground/50 focus:outline-none focus:ring-2 focus:ring-primary-cta"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-6">
|
||||
<label className="block text-sm font-semibold text-foreground mb-2">Product Description</label>
|
||||
<textarea
|
||||
name="description"
|
||||
value={formData.description}
|
||||
onChange={handleInputChange}
|
||||
rows={4}
|
||||
className="w-full px-4 py-2 border border-accent/20 rounded-lg bg-background text-foreground placeholder-foreground/50 focus:outline-none focus:ring-2 focus:ring-primary-cta resize-none"
|
||||
placeholder="Enter product description..."
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Action Buttons */}
|
||||
<div className="mt-8 pt-8 border-t border-accent/20 flex gap-4">
|
||||
<button
|
||||
onClick={handleSave}
|
||||
disabled={isSaving}
|
||||
className="flex-1 flex items-center justify-center gap-2 bg-primary-cta hover:bg-primary-cta/90 disabled:opacity-50 text-foreground font-semibold py-3 px-6 rounded-lg transition-all"
|
||||
>
|
||||
<Save size={20} />
|
||||
{isSaving ? "Saving..." : "Save Changes"}
|
||||
</button>
|
||||
|
||||
<button
|
||||
onClick={handleReset}
|
||||
className="flex-1 flex items-center justify-center gap-2 border border-accent/20 hover:bg-background/50 text-foreground font-semibold py-3 px-6 rounded-lg transition-all"
|
||||
>
|
||||
<X size={20} />
|
||||
Reset Form
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Info Section */}
|
||||
<div className="mt-8 bg-background-accent/30 border border-accent/20 rounded-lg p-6">
|
||||
<h3 className="font-semibold text-foreground mb-2">💡 Tip</h3>
|
||||
<p className="text-foreground/70 text-sm">
|
||||
Changes to product details, pricing, and inventory are saved immediately and reflected across all sales channels. Product images update within 5 minutes.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="footer" data-section="footer">
|
||||
<FooterMedia
|
||||
imageSrc="https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3AiptcO4QrzBpwIQbUIl2kal97h/abstract-dark-tech-background-with-flowi-1773085532519-883f666b.png"
|
||||
imageAlt="Tech abstract background"
|
||||
logoText="TechVault"
|
||||
copyrightText="© 2025 TechVault | Powering Tech E-Commerce"
|
||||
columns={[
|
||||
{
|
||||
title: "Product", items: [
|
||||
{ label: "Features", href: "#features" },
|
||||
{ label: "Pricing", href: "#pricing" },
|
||||
{ label: "Security", href: "#" },
|
||||
{ label: "Updates", href: "#" }
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "Company", items: [
|
||||
{ label: "About", href: "#" },
|
||||
{ label: "Blog", href: "#" },
|
||||
{ label: "Careers", href: "#" },
|
||||
{ label: "Contact", href: "#contact" }
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "Legal", items: [
|
||||
{ label: "Privacy Policy", href: "#" },
|
||||
{ label: "Terms of Service", href: "#" },
|
||||
{ label: "Cookie Policy", href: "#" },
|
||||
{ label: "Compliance", href: "#" }
|
||||
]
|
||||
}
|
||||
]}
|
||||
containerClassName="max-w-7xl mx-auto"
|
||||
/>
|
||||
</div>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user