import { cva, type VariantProps } from 'class-variance-authority' export const badgeVariants = cva( 'inline-flex items-center gap-1.5 rounded-full px-2.5 py-0.5 text-xs font-medium transition-colors', { variants: { variant: { running: 'bg-emerald-500/15 text-emerald-400 border border-emerald-500/30', pending: 'bg-amber-500/15 text-amber-400 border border-amber-500/30', waking: 'bg-amber-500/15 text-amber-400 border border-amber-500/30', success: 'bg-emerald-500/15 text-emerald-400 border border-emerald-500/30', error: 'bg-rose-500/15 text-rose-400 border border-rose-500/30', info: 'bg-sky-500/15 text-sky-400 border border-sky-500/30', neutral: 'bg-zinc-500/15 text-zinc-400 border border-zinc-500/30', }, }, defaultVariants: { variant: 'neutral', }, } ) export type BadgeVariant = VariantProps['variant'] const STATUS_TO_VARIANT: Record = { running: 'running', pending: 'pending', waking: 'pending', success: 'success', error: 'error', failed: 'error', completed: 'success', cancelled: 'neutral', info: 'info', unknown: 'neutral', online: 'success', offline: 'error', } export function statusVariant(status: string): BadgeVariant { return STATUS_TO_VARIANT[status.toLowerCase()] ?? 'neutral' } export function statusLabel(status: string): string { const labels: Record = { running: 'Running', pending: 'Pending', waking: 'Waking', success: 'Success', error: 'Error', failed: 'Failed', completed: 'Completed', cancelled: 'Cancelled', info: 'Info', unknown: 'Unknown', } return labels[status.toLowerCase()] ?? status } export interface ErrorCodeInfo { title: string; hint: string; } const ERROR_CODES: Record = { wol_timeout: { title: "Machine didn't wake up", hint: 'Waited for machine to respond and got no SSH reply. Make sure the server and the target machine are on the same L2 broadcast domain. For HP Microservers and similar hardware, increase the Wake timeout in the machine settings (180s or more).', }, wol_send_failed: { title: 'Wake-on-LAN packet failed to send', hint: 'The magic packet could not be sent. Check the server logs for details. The server must be on the same broadcast domain as the target machine NIC and must have NET_ADMIN or CAP_NET_RAW capability.', }, rsync_error: { title: 'rsync failed', hint: 'See the full log for rsync error details', }, exit_code: { title: 'rsync exited with errors', hint: 'Check stderr output for details', }, ssh_key_fallback: { title: 'SSH key not found', hint: 'Server fell back to its own key. Verify the machine SSH key configuration', }, cancelled_user: { title: 'Cancelled by user', hint: 'The job was manually cancelled from the UI', }, cancelled_shutdown: { title: 'Cancelled — server shutdown', hint: 'The job was interrupted because the syncserver process stopped', }, unknown_cancelled: { title: 'Cancelled (no reason recorded)', hint: 'This cancellation happened before the upgrade that records reasons', }, } export function getErrorCodeInfo(code: string | null | undefined): ErrorCodeInfo | null { if (!code) return null return ERROR_CODES[code] ?? { title: code, hint: 'See full error details below' } }