feat(wizard): add eye-catcher shake animation for missing required categories
All checks were successful
Staging Build / build (push) Successful in 3m41s

This commit is contained in:
DanielS
2026-08-18 16:43:22 +02:00
parent 9dbbbb8b31
commit ea1906f9e4
3 changed files with 96 additions and 36 deletions

View File

@@ -88,34 +88,52 @@ export function StepSoftware({
className="space-y-6"
>
{/* Category header */}
<div className="flex items-center gap-3 bg-white/5 p-4 rounded-xl border border-white/10">
<div className="w-8 h-8 rounded-lg bg-primary/20 flex items-center justify-center">
<CategoryIcon icon={currentCategory.icon} className="w-4 h-4 text-primary" />
</div>
<div>
<h3 className="font-bold text-white text-sm">{currentCategory.name}</h3>
{currentCategory.description && (
<p className="text-slate-400 text-xs mt-0.5">{currentCategory.description}</p>
)}
</div>
{sel?.productIds && sel.productIds.length > 0 ? (
<Badge className="ml-auto bg-green-500/20 text-green-400 border border-green-500/30 text-xs rounded-full">
<Check className="w-3 h-3 mr-1" /> {sel.productIds.length} Ausgewählt
</Badge>
) : sel?.productId ? (
<Badge className="ml-auto bg-green-500/20 text-green-400 border border-green-500/30 text-xs rounded-full">
<Check className="w-3 h-3 mr-1" /> Ausgewählt
</Badge>
) : currentCategory.is_required ? (
<Badge variant="destructive" className="ml-auto opacity-90 text-xs rounded-full bg-red-500/20 text-red-400 border border-red-500/30">
<AlertCircle className="w-3 h-3 mr-1" /> Erforderlich
</Badge>
) : (
<Badge variant="outline" className="ml-auto border-white/10 text-slate-400 text-xs rounded-full bg-white/5">
Optional
</Badge>
)}
</div>
{(() => {
const isMissingRequired = currentCategory.is_required && !sel?.productId && (!sel?.productIds || sel.productIds.length === 0)
return (
<div className={`flex items-center gap-3 p-4 rounded-xl border transition-all ${
isMissingRequired
? 'animate-eye-catcher bg-red-500/10 border-red-500 text-red-400 font-bold'
: 'bg-white/5 border-white/10'
}`}>
<div className={`w-8 h-8 rounded-lg flex items-center justify-center ${
isMissingRequired ? 'bg-red-500/20 text-red-400' : 'bg-primary/20 text-primary'
}`}>
<CategoryIcon icon={currentCategory.icon} className="w-4 h-4" />
</div>
<div>
<h3 className="font-bold text-white text-sm flex items-center gap-2">
{currentCategory.name}
{isMissingRequired && (
<span className="text-[10px] bg-red-500/20 text-red-400 border border-red-500/40 px-2 py-0.5 rounded-full font-extrabold animate-pulse tracking-wider">
PFLICHTFELD AUSWÄHLEN!
</span>
)}
</h3>
{currentCategory.description && (
<p className="text-slate-400 text-xs mt-0.5">{currentCategory.description}</p>
)}
</div>
{sel?.productIds && sel.productIds.length > 0 ? (
<Badge className="ml-auto bg-green-500/20 text-green-400 border border-green-500/30 text-xs rounded-full">
<Check className="w-3 h-3 mr-1" /> {sel.productIds.length} Ausgewählt
</Badge>
) : sel?.productId ? (
<Badge className="ml-auto bg-green-500/20 text-green-400 border border-green-500/30 text-xs rounded-full">
<Check className="w-3 h-3 mr-1" /> Ausgewählt
</Badge>
) : currentCategory.is_required ? (
<Badge variant="destructive" className="ml-auto opacity-90 text-xs rounded-full bg-red-500/30 text-red-400 border border-red-500/50 animate-pulse font-extrabold">
<AlertCircle className="w-3 h-3 mr-1 text-red-400" /> Bitte auswählen!
</Badge>
) : (
<Badge variant="outline" className="ml-auto border-white/10 text-slate-400 text-xs rounded-full bg-white/5">
Optional
</Badge>
)}
</div>
)
})()}
{catProducts.length === 0 ? (
<p className="text-slate-500 text-sm italic">