refactor(shop): extract wizard validation and email templates into helpers
All checks were successful
Staging Build / build (push) Successful in 2m48s
All checks were successful
Staging Build / build (push) Successful in 2m48s
This commit is contained in:
74
shop/lib/actions/validation.ts
Normal file
74
shop/lib/actions/validation.ts
Normal file
@@ -0,0 +1,74 @@
|
||||
import { WizardSelections, Product, Category } from '@/lib/types'
|
||||
|
||||
export function validateWizardSelections(
|
||||
selections: WizardSelections,
|
||||
dbProducts: Product[],
|
||||
dbCategories: Category[]
|
||||
): void {
|
||||
for (const cat of dbCategories) {
|
||||
const sel = selections[cat.id]
|
||||
if (cat.is_required && (!sel || !sel.productId)) {
|
||||
throw new Error(`Die Kategorie "${cat.name}" ist ein Pflichtfeld, wurde aber nicht ausgewählt.`)
|
||||
}
|
||||
if (sel?.productId) {
|
||||
const prod = dbProducts.find(p => p.id === sel.productId)
|
||||
if (!prod) {
|
||||
throw new Error(`Das ausgewählte Produkt für Kategorie "${cat.name}" wurde nicht gefunden.`)
|
||||
}
|
||||
|
||||
// Validate selected modules
|
||||
for (const mId of sel.moduleIds) {
|
||||
const mod = prod.modules?.find(m => m.id === mId)
|
||||
if (!mod) {
|
||||
throw new Error(`Das Modul mit ID "${mId}" gehört nicht zum Produkt "${prod.name}".`)
|
||||
}
|
||||
// Requirements check
|
||||
if (mod.requirements && mod.requirements.length > 0) {
|
||||
const hasMetRequirement = mod.requirements.some(reqId => sel.moduleIds.includes(reqId))
|
||||
if (!hasMetRequirement) {
|
||||
throw new Error(`Das Modul "${mod.name}" setzt die Aktivierung mindestens eines der folgenden Module voraus: ${mod.requirements.join(', ')}.`)
|
||||
}
|
||||
}
|
||||
// Exclusions check
|
||||
if (mod.exclusions && mod.exclusions.length > 0) {
|
||||
const conflicting = mod.exclusions.filter(exId => sel.moduleIds.includes(exId))
|
||||
if (conflicting.length > 0) {
|
||||
throw new Error(`Das Modul "${mod.name}" schließt die Kombination mit anderen gewählten Modulen aus.`)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Product-level constraints validation
|
||||
const selectedProductIds = Object.values(selections)
|
||||
.map(s => s.productId)
|
||||
.filter((id): id is string => !!id)
|
||||
|
||||
for (const prodId of selectedProductIds) {
|
||||
const prod = dbProducts.find(p => p.id === prodId)
|
||||
if (!prod) continue
|
||||
|
||||
// Product requirements check
|
||||
if (prod.requirements && prod.requirements.length > 0) {
|
||||
const hasMetRequirement = prod.requirements.some(reqId => selectedProductIds.includes(reqId))
|
||||
if (!hasMetRequirement) {
|
||||
const reqNames = prod.requirements
|
||||
.map(reqId => dbProducts.find(p => p.id === reqId)?.name || reqId)
|
||||
.join(' oder ')
|
||||
throw new Error(`Das Produkt "${prod.name}" erfordert die Auswahl von mindestens einem dieser Produkte: ${reqNames}.`)
|
||||
}
|
||||
}
|
||||
|
||||
// Product exclusions check
|
||||
if (prod.exclusions && prod.exclusions.length > 0) {
|
||||
const conflicting = prod.exclusions.filter(exId => selectedProductIds.includes(exId))
|
||||
if (conflicting.length > 0) {
|
||||
const conflictingNames = conflicting
|
||||
.map(exId => dbProducts.find(p => p.id === exId)?.name || exId)
|
||||
.join(', ')
|
||||
throw new Error(`Das Produkt "${prod.name}" schließt die gleichzeitige Auswahl von folgenden Produkten aus: ${conflictingNames}.`)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user