diff --git a/shop/components/admin/category-dialog.tsx b/shop/components/admin/category-dialog.tsx index 1502960..17e91d7 100644 --- a/shop/components/admin/category-dialog.tsx +++ b/shop/components/admin/category-dialog.tsx @@ -46,6 +46,8 @@ const categorySchema = z.object({ allow_multiselect: z.boolean().default(false), free_items_limit: z.coerce.number().int().min(0).default(0), preselect: z.boolean().default(true), + show_in_kauf: z.boolean().default(true), + show_in_abo: z.boolean().default(true), }) type CategoryFormValues = z.infer @@ -71,6 +73,8 @@ export function CategoryDialog({ allow_multiselect: category?.allow_multiselect ?? false, free_items_limit: category?.free_items_limit ?? 0, preselect: category?.preselect ?? true, + show_in_kauf: category?.show_in_kauf ?? true, + show_in_abo: category?.show_in_abo ?? true, }, }) @@ -264,6 +268,54 @@ export function CategoryDialog({ )} /> )} + +
+ ( + + + + +
+ + In Kauf anzeigen + +

+ Im Kauf-Zweig des Wizards anzeigen. +

+
+
+ )} + /> + ( + + + + +
+ + In Abo anzeigen + +

+ Im Abo-Zweig des Wizards anzeigen. +

+
+
+ )} + /> +
+ {form.watch('allow_multiselect') && ( { + return categories.filter(cat => + selectedBillingInterval === 'one_time' + ? cat.show_in_kauf !== false + : cat.show_in_abo !== false + ) + }, [categories, selectedBillingInterval]) + // Per-category selection map: categoryId -> { productId, productIds, moduleIds } const [selections, setSelections] = useState>(() => { + const initInterval = initialOrder?.order_data?.billing_cycle ?? 'monthly' const init: Record = {} categories.forEach(cat => { if (initialOrder) { @@ -211,10 +220,11 @@ export function OrderWizard({ return } } - if (cat.allow_multiselect || cat.preselect === false) { + const isVisible = initInterval === 'one_time' ? cat.show_in_kauf !== false : cat.show_in_abo !== false + if (!isVisible || cat.allow_multiselect || cat.preselect === false) { init[cat.id] = { productId: null, productIds: [], moduleIds: [] } } else { - const first = products.find(p => p.category_id === cat.id && p.show_in_abo !== false) + const first = products.find(p => p.category_id === cat.id && (initInterval === 'one_time' ? p.show_in_kauf !== false : p.show_in_abo !== false)) init[cat.id] = { productId: first?.id ?? null, productIds: first ? [first.id] : [], moduleIds: [] } } }) @@ -223,7 +233,7 @@ export function OrderWizard({ // Only REQUIRED categories must have a product selected (which must be filtered by selected branch) const allCategoriesFilled = useMemo(() => { - return categories + return visibleCategories .filter(cat => cat.is_required) .every(cat => { const sel = selections[cat.id] @@ -243,7 +253,7 @@ export function OrderWizard({ ? prod.show_in_kauf !== false : prod.show_in_abo !== false }) - }, [categories, selections, products, selectedBillingInterval]) + }, [visibleCategories, selections, products, selectedBillingInterval]) // Product validation errors (requirements and exclusions) const productValidationErrors = useMemo(() => { @@ -459,7 +469,8 @@ export function OrderWizard({ } const newSelections: Record = {} categories.forEach(cat => { - if (cat.allow_multiselect || cat.preselect === false) { + const isVisible = val === 'one_time' ? cat.show_in_kauf !== false : cat.show_in_abo !== false + if (!isVisible || cat.allow_multiselect || cat.preselect === false) { newSelections[cat.id] = { productId: null, productIds: [], moduleIds: [] } } else { const matchingProd = products.find(p => @@ -870,7 +881,7 @@ export function OrderWizard({ - {categories.map((cat, idx) => { + {visibleCategories.map((cat, idx) => { const otherSelectedProductIds = Object.entries(selections) .filter(([cId]) => cId !== cat.id) .map(([, s]) => s.productId) @@ -1122,7 +1133,7 @@ export function OrderWizard({ Zusammenfassung - {categories.map(cat => { + {visibleCategories.map(cat => { const sel = selections[cat.id] const selectedProds: Product[] = [] if (cat.allow_multiselect && sel?.productIds) { @@ -1311,7 +1322,7 @@ export function OrderWizard({
- {categories.map(cat => { + {visibleCategories.map(cat => { const sel = selections[cat.id] const selectedProds: Product[] = [] if (cat.allow_multiselect && sel?.productIds) { diff --git a/shop/lib/types.ts b/shop/lib/types.ts index 1c49a56..18ba045 100644 --- a/shop/lib/types.ts +++ b/shop/lib/types.ts @@ -29,6 +29,8 @@ export type Category = { allow_multiselect: boolean free_items_limit: number preselect: boolean + show_in_kauf?: boolean + show_in_abo?: boolean created_at: string } diff --git a/shop/supabase/migrations/20260709142500_add_show_in_branches_to_categories.sql b/shop/supabase/migrations/20260709142500_add_show_in_branches_to_categories.sql new file mode 100644 index 0000000..b343257 --- /dev/null +++ b/shop/supabase/migrations/20260709142500_add_show_in_branches_to_categories.sql @@ -0,0 +1,3 @@ +-- Add show_in_kauf and show_in_abo columns to categories table +ALTER TABLE public.categories ADD COLUMN IF NOT EXISTS show_in_kauf BOOLEAN DEFAULT true NOT NULL; +ALTER TABLE public.categories ADD COLUMN IF NOT EXISTS show_in_abo BOOLEAN DEFAULT true NOT NULL;