@props(['status', 'pulse' => false]) {{-- One definition of what each licence state looks like, so a badge cannot drift between the grid, the drawer and any later page. --}} @php $map = [ 'active' => ['Active', 'bg-emerald-50 text-emerald-700 ring-emerald-600/20 dark:bg-emerald-500/10 dark:text-emerald-400 dark:ring-emerald-500/30', 'bg-emerald-500'], 'expiring' => ['Expiring Soon', 'bg-amber-50 text-amber-700 ring-amber-600/20 dark:bg-amber-500/10 dark:text-amber-400 dark:ring-amber-500/30', 'bg-amber-500'], 'suspended' => ['Suspended', 'bg-orange-50 text-orange-700 ring-orange-600/20 dark:bg-orange-500/10 dark:text-orange-400 dark:ring-orange-500/30', 'bg-orange-500'], 'expired' => ['Expired', 'bg-red-50 text-red-700 ring-red-600/20 dark:bg-red-500/10 dark:text-red-400 dark:ring-red-500/30', 'bg-red-500'], 'revoked' => ['Revoked', 'bg-slate-100 text-slate-600 ring-slate-500/20 dark:bg-slate-500/10 dark:text-slate-400 dark:ring-slate-500/30', 'bg-slate-500'], 'pending' => ['Pending', 'bg-blue-50 text-blue-700 ring-blue-600/20 dark:bg-blue-500/10 dark:text-blue-400 dark:ring-blue-500/30', 'bg-blue-500'], 'none' => ['No licence', 'bg-slate-100 text-slate-500 ring-slate-400/20 dark:bg-slate-700/40 dark:text-slate-400 dark:ring-slate-600/30', 'bg-slate-400'], // Packages are offered or withdrawn rather than expiring, so they need // their own word - "revoked" would read as something having gone wrong. 'inactive' => ['Inactive', 'bg-slate-100 text-slate-600 ring-slate-500/20 dark:bg-white/5 dark:text-slate-400 dark:ring-white/10', 'bg-slate-400'], // Installation check-in states. Derived from next_verification_at, which // is the schedule the server itself hands the client - so "overdue" // means the install has genuinely missed its own appointment. 'verified' => ['Verified', 'bg-emerald-50 text-emerald-700 ring-emerald-600/20 dark:bg-emerald-500/10 dark:text-emerald-400 dark:ring-emerald-500/30', 'bg-emerald-500'], 'overdue' => ['Overdue', 'bg-amber-50 text-amber-700 ring-amber-600/20 dark:bg-amber-500/10 dark:text-amber-400 dark:ring-amber-500/30', 'bg-amber-500'], 'offline' => ['Offline', 'bg-slate-100 text-slate-600 ring-slate-500/20 dark:bg-white/5 dark:text-slate-400 dark:ring-white/10', 'bg-slate-400'], 'blocked' => ['Blocked', 'bg-red-50 text-red-700 ring-red-600/20 dark:bg-red-500/10 dark:text-red-400 dark:ring-red-500/30', 'bg-red-500'], // Release lifecycle. "Archived" is what a rollback leaves behind, so it // reads as a deliberate withdrawal rather than as an error. 'published' => ['Published', 'bg-emerald-50 text-emerald-700 ring-emerald-600/20 dark:bg-emerald-500/10 dark:text-emerald-400 dark:ring-emerald-500/30', 'bg-emerald-500'], 'draft' => ['Draft', 'bg-slate-100 text-slate-600 ring-slate-500/20 dark:bg-white/5 dark:text-slate-400 dark:ring-white/10', 'bg-slate-400'], 'hidden' => ['Hidden', 'bg-amber-50 text-amber-700 ring-amber-600/20 dark:bg-amber-500/10 dark:text-amber-400 dark:ring-amber-500/30', 'bg-amber-500'], 'archived' => ['Archived', 'bg-slate-100 text-slate-500 ring-slate-400/20 dark:bg-white/5 dark:text-slate-500 dark:ring-white/10', 'bg-slate-500'], ]; [$label, $classes, $dot] = $map[$status] ?? $map['none']; @endphp {{-- `pulse` is opt-in: a badge that animates everywhere is noise, but a live state (active now, expiring now) reads better with a heartbeat than without one. Respects prefers-reduced-motion via Tailwind's motion-safe. --}} merge(['class' => "inline-flex items-center gap-1.5 whitespace-nowrap rounded-full px-2.5 py-1 text-xs font-medium ring-1 ring-inset {$classes}"]) }}> {{ $label }}