fix: disable incompatible sub-products in wizard and prevent bottom-up reset
This commit is contained in:
@@ -203,6 +203,19 @@ export function OrderWizard({
|
||||
)
|
||||
}, [categories, selectedBillingInterval])
|
||||
|
||||
const isProductDisabled = (product: Product, currentCategoryId: string) => {
|
||||
const baseCategoryId = visibleCategories[0]?.id
|
||||
if (!baseCategoryId || currentCategoryId === baseCategoryId) return false
|
||||
|
||||
const baseProductId = selections[baseCategoryId]?.productId
|
||||
if (!baseProductId) return false
|
||||
|
||||
const baseProduct = products.find(p => p.id === baseProductId)
|
||||
if (!baseProduct) return false
|
||||
|
||||
return baseProduct.exclusions?.includes(product.id) || product.exclusions?.includes(baseProductId)
|
||||
}
|
||||
|
||||
// Per-category selection map: categoryId -> { productId, productIds, moduleIds }
|
||||
const [selections, setSelections] = useState<Record<string, CategorySelection>>(() => {
|
||||
const initInterval = initialOrder?.order_data?.billing_cycle ?? 'monthly'
|
||||
@@ -970,20 +983,24 @@ export function OrderWizard({
|
||||
<div className="grid gap-3">
|
||||
{catProducts.map(product => {
|
||||
const isChecked = sel?.productIds?.includes(product.id) ?? false
|
||||
const disabled = isProductDisabled(product, cat.id)
|
||||
return (
|
||||
<div key={product.id} className="relative">
|
||||
<Label
|
||||
onClick={() => selectProduct(cat.id, product.id)}
|
||||
className={`flex flex-col items-start p-4 rounded-xl border-2 cursor-pointer transition-all ${
|
||||
isChecked
|
||||
? 'border-primary bg-primary/5'
|
||||
: 'border-white/5 bg-white/5 hover:bg-white/10'
|
||||
onClick={() => !disabled && selectProduct(cat.id, product.id)}
|
||||
className={`flex flex-col items-start p-4 rounded-xl border-2 transition-all ${
|
||||
disabled
|
||||
? 'border-white/5 bg-white/5 opacity-50 cursor-not-allowed'
|
||||
: isChecked
|
||||
? 'border-primary bg-primary/5 cursor-pointer'
|
||||
: 'border-white/5 bg-white/5 hover:bg-white/10 cursor-pointer'
|
||||
}`}
|
||||
>
|
||||
<div className="flex justify-between w-full items-center">
|
||||
<div className="flex items-center gap-3">
|
||||
<Checkbox
|
||||
checked={isChecked}
|
||||
disabled={disabled}
|
||||
onCheckedChange={() => {}} // onClick on label handles it
|
||||
className="border-white/20 data-[state=checked]:bg-primary"
|
||||
/>
|
||||
@@ -1019,17 +1036,24 @@ export function OrderWizard({
|
||||
onValueChange={id => selectProduct(cat.id, id)}
|
||||
className="grid gap-3"
|
||||
>
|
||||
{catProducts.map(product => (
|
||||
<div key={product.id} className="relative">
|
||||
<RadioGroupItem
|
||||
value={product.id}
|
||||
id={`${cat.id}-${product.id}`}
|
||||
className="peer sr-only"
|
||||
/>
|
||||
<Label
|
||||
htmlFor={`${cat.id}-${product.id}`}
|
||||
className="flex flex-col items-start p-4 rounded-xl border-2 border-white/5 bg-white/5 hover:bg-white/10 peer-data-[state=checked]:border-primary peer-data-[state=checked]:bg-primary/5 cursor-pointer transition-all"
|
||||
>
|
||||
{catProducts.map(product => {
|
||||
const disabled = isProductDisabled(product, cat.id)
|
||||
return (
|
||||
<div key={product.id} className="relative">
|
||||
<RadioGroupItem
|
||||
value={product.id}
|
||||
id={`${cat.id}-${product.id}`}
|
||||
disabled={disabled}
|
||||
className="peer sr-only"
|
||||
/>
|
||||
<Label
|
||||
htmlFor={disabled ? undefined : `${cat.id}-${product.id}`}
|
||||
className={`flex flex-col items-start p-4 rounded-xl border-2 border-white/5 bg-white/5 transition-all ${
|
||||
disabled
|
||||
? 'opacity-50 cursor-not-allowed'
|
||||
: 'hover:bg-white/10 peer-data-[state=checked]:border-primary peer-data-[state=checked]:bg-primary/5 cursor-pointer'
|
||||
}`}
|
||||
>
|
||||
<div className="flex justify-between w-full items-center">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="font-bold text-base text-white">{product.name}</span>
|
||||
|
||||
Reference in New Issue
Block a user