'use client' import { useState, useEffect } from 'react' import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' import { Label } from '@/components/ui/label' import { Textarea } from '@/components/ui/textarea' import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card' import { Badge } from '@/components/ui/badge' import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table' import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select' import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from '@/components/ui/dialog' import { Alert, AlertDescription } from '@/components/ui/alert' import { Plus, Search, Edit, Trash2, Save, X, AlertCircle, CheckCircle, DollarSign, Package, Image } from 'lucide-react' import type { Product } from '@/lib/products/types' interface ProductFormData { name: string description: string price: string currency: string images: string[] metadata: Record } const initialFormData: ProductFormData = { name: '', description: '', price: '', currency: 'usd', images: [], metadata: {} } const currencyOptions = [ { value: 'usd', label: 'USD ($)' }, { value: 'eur', label: 'EUR (€)' }, { value: 'gbp', label: 'GBP (£)' }, { value: 'cad', label: 'CAD ($)' }, { value: 'aud', label: 'AUD ($)' } ] export function ProductAdmin() { const [products, setProducts] = useState([]) const [loading, setLoading] = useState(true) const [searchTerm, setSearchTerm] = useState('') const [selectedProducts, setSelectedProducts] = useState([]) const [showCreateDialog, setShowCreateDialog] = useState(false) const [editingProduct, setEditingProduct] = useState(null) const [isSaving, setIsSaving] = useState(false) const [error, setError] = useState(null) const [success, setSuccess] = useState(null) const [formData, setFormData] = useState(initialFormData) // Fetch products const fetchProducts = async () => { try { setLoading(true) const response = await fetch('/api/products/admin') if (!response.ok) throw new Error('Failed to fetch products') const data = await response.json() setProducts(data.products) } catch (err) { setError(err instanceof Error ? err.message : 'Failed to fetch products') } finally { setLoading(false) } } useEffect(() => { fetchProducts() }, []) // Handle form input changes const handleInputChange = (field: keyof ProductFormData, value: any) => { setFormData(prev => ({ ...prev, [field]: value })) } // Handle metadata input changes const handleMetadataChange = (key: string, value: string) => { setFormData(prev => ({ ...prev, metadata: { ...prev.metadata, [key]: value } })) } // Add metadata field const addMetadataField = () => { const emptyKey = Object.keys(formData.metadata).length === 0 ? 'category' : `key${Object.keys(formData.metadata).length + 1}` setFormData(prev => ({ ...prev, metadata: { ...prev.metadata, [emptyKey]: '' } })) } // Remove metadata field const removeMetadataField = (key: string) => { setFormData(prev => { const newMetadata = { ...prev.metadata } delete newMetadata[key] return { ...prev, metadata: newMetadata } }) } // Create product const handleCreateProduct = async () => { try { setIsSaving(true) setError(null) setSuccess(null) // Validate form if (!formData.name || !formData.price) { setError('Name and price are required') return } const price = parseFloat(formData.price) if (isNaN(price) || price <= 0) { setError('Price must be a valid positive number') return } const response = await fetch('/api/products/admin', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ name: formData.name, description: formData.description, price, currency: formData.currency, images: formData.images.filter(Boolean), metadata: formData.metadata }), }) if (!response.ok) { const errorData = await response.json() throw new Error(errorData.error || 'Failed to create product') } const newProduct = await response.json() setProducts(prev => [newProduct.product, ...prev]) setSuccess(`Product "${newProduct.product.name}" created successfully`) // Reset form setFormData(initialFormData) setShowCreateDialog(false) } catch (err) { setError(err instanceof Error ? err.message : 'Failed to create product') } finally { setIsSaving(false) } } // Update product (placeholder - would need implementation) const handleUpdateProduct = async (product: Product) => { try { setIsSaving(true) setError(null) setSuccess(null) // In a real implementation, you would call the update API console.log('Updating product:', product) setSuccess(`Product "${product.name}" updated successfully`) setEditingProduct(null) } catch (err) { setError(err instanceof Error ? err.message : 'Failed to update product') } finally { setIsSaving(false) } } // Delete product (placeholder - would need implementation) const handleDeleteProduct = async (productId: string) => { try { if (!confirm('Are you sure you want to delete this product? This action cannot be undone.')) { return } setLoading(true) setError(null) // In a real implementation, you would call the delete API console.log('Deleting product:', productId) setProducts(prev => prev.filter(p => p.id !== productId)) setSuccess('Product deleted successfully') } catch (err) { setError(err instanceof Error ? err.message : 'Failed to delete product') } finally { setLoading(false) } } // Bulk actions const handleBulkAction = async (action: 'deactivate') => { try { setLoading(true) setError(null) const response = await fetch('/api/products/admin', { method: 'PUT', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ action, productIds: selectedProducts }), }) if (!response.ok) { throw new Error('Failed to perform bulk action') } await fetchProducts() setSelectedProducts([]) setSuccess(`Successfully ${action}d ${selectedProducts.length} product(s)`) } catch (err) { setError(err instanceof Error ? err.message : 'Failed to perform bulk action') } finally { setLoading(false) } } // Filter products based on search const filteredProducts = products.filter(product => product.name.toLowerCase().includes(searchTerm.toLowerCase()) || product.description?.toLowerCase().includes(searchTerm.toLowerCase()) ) // Clear alerts useEffect(() => { if (error || success) { const timer = setTimeout(() => { setError(null) setSuccess(null) }, 5000) return () => clearTimeout(timer) } }, [error, success]) return (
{/* Alerts */} {error && ( {error} )} {success && ( {success} )} {/* Header */}

Product Management

Manage your Stripe products and inventory

Create New Product Add a new product to your Stripe inventory.
handleInputChange('name', e.target.value)} placeholder="Enter product name" />
handleInputChange('price', e.target.value)} placeholder="0.00" />