/** * Cart Rules Tab for Quantity Limits * * This is a Pro feature that allows setting cart-level quantity and spend restrictions. */ import { useState, useEffect } from "react" import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" import { Label } from "@/components/ui/label" import { Input } from "@/components/ui/input" import { Switch } from "@/components/ui/switch" import { Checkbox } from "@/components/ui/checkbox" import { Button } from "@/components/ui/button" import { Badge } from "@/components/ui/badge" import { ShoppingCart, X, Search, Loader2, Package } from "lucide-react" import { useProductSearch } from "../../hooks" import type { CartRules, ProductSearchResult } from "../../types" interface CartRulesTabProps { rules: CartRules onChange: (rules: CartRules) => void } export function CartRulesTab({ rules, onChange }: CartRulesTabProps) { const [searchQuery, setSearchQuery] = useState('') const [excludedProductNames, setExcludedProductNames] = useState>(new Map()) const { products: searchResults, isSearching, searchProducts, clearResults } = useProductSearch() // Get currency info from Pro plugin (if available) const currency = window.swiftCommerceData?.currency const currencySymbol = currency?.symbol || '$' const currencyCode = currency?.code || 'USD' // Debounced search useEffect(() => { const timer = setTimeout(() => { if (searchQuery.length >= 2) { searchProducts(searchQuery) } else { clearResults() } }, 300) return () => clearTimeout(timer) }, [searchQuery]) const handleChange = (field: K, value: CartRules[K]) => { onChange({ ...rules, [field]: value }) } const addExcludedProduct = (product: ProductSearchResult) => { const currentExcluded = rules.excluded_products || [] if (!currentExcluded.includes(product.id)) { handleChange('excluded_products', [...currentExcluded, product.id]) setExcludedProductNames(new Map(excludedProductNames.set(product.id, product.name))) } setSearchQuery('') clearResults() } const removeExcludedProduct = (productId: number) => { const currentExcluded = rules.excluded_products || [] handleChange('excluded_products', currentExcluded.filter(id => id !== productId)) const newNames = new Map(excludedProductNames) newNames.delete(productId) setExcludedProductNames(newNames) } return (
{/* Cart Quantity Restrictions */} Cart Quantity Restrictions Set minimum and maximum number of items allowed in the cart.
handleChange('min_qty_restriction', parseInt(e.target.value) || 0)} placeholder="0" />

Minimum number of items in cart. Set zero for no restrictions.

handleChange('max_qty_restriction', parseInt(e.target.value) || 0)} placeholder="0" />

Maximum number of items in cart. Set zero for no restrictions.

{/* Cart Spend Restrictions */} Cart Spend Restrictions Set minimum and maximum spend amounts for the cart in {currencyCode} ({currencySymbol}).
{/* Enable spend restrictions toggle */}
handleChange('enable_spend', checked)} />
{rules.enable_spend && (
{currencySymbol} handleChange('min_spend', parseFloat(e.target.value) || 0)} placeholder="0" style={{ paddingLeft: `${Math.max(2.5, currencySymbol.length * 0.6 + 1)}rem` }} />

Minimum spend for items in cart. Set zero for no restrictions.

{currencySymbol} handleChange('max_spend', parseFloat(e.target.value) || 0)} placeholder="0" style={{ paddingLeft: `${Math.max(2.5, currencySymbol.length * 0.6 + 1)}rem` }} />

Maximum spend for items in cart. Set zero for no restrictions.

handleChange('include_shipping', checked as boolean)} />
)}
{/* Excluded Products - Full Width */} Excluded Products These products will be excluded from cart quantity and spend calculations.
{/* Search */}
setSearchQuery(e.target.value)} /> {isSearching && ( )} {/* Search Results Dropdown */} {searchResults.length > 0 && (
{searchResults.map((product) => ( ))}
)}
{/* Excluded Products List */} {(rules.excluded_products?.length || 0) > 0 ? (
{rules.excluded_products.map((productId) => ( {excludedProductNames.get(productId) || `Product #${productId}`} ))}
) : (

No products excluded. Search and select products above.

)}
) }