{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "cloud-backup-schedule",
  "title": "Cloud Backup Schedule",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-angular/blocks/cloud-backup-schedule/cloud-backup-schedule.component.ts",
      "content": "// Automated cloud snapshot scheduler: an automation tile with a toggle, a storage quota\n// gauge, and a recent-snapshot ledger. \"Backup Now\" simulates a 1.2s snapshot and prepends it.\nimport { Component, DestroyRef, Input, OnInit, inject, signal, ChangeDetectionStrategy } from '@angular/core'\nimport {\n  AlertCircle,\n  ArrowUpRight,\n  Calendar,\n  CheckCircle2,\n  Clock,\n  Cloud,\n  Database,\n  HardDrive,\n  LucideAngularModule,\n  Play,\n  RotateCw,\n  ShieldCheck,\n} from 'lucide-angular'\nimport { cn } from '@/lib/utils'\nimport {\n  UiCardComponent,\n  UiCardContentComponent,\n  UiCardDescriptionComponent,\n  UiCardFooterComponent,\n  UiCardHeaderComponent,\n  UiCardTitleComponent,\n} from '@/ui/card/card.component'\nimport { UiButtonComponent } from '@/ui/button/button.component'\nimport { UiBadgeComponent, type BadgeVariant } from '@/ui/badge/badge.component'\nimport { UiProgressComponent } from '@/ui/progress/progress.component'\nimport { UiSwitchComponent } from '@/ui/switch/switch.component'\nimport { UiSeparatorComponent } from '@/ui/separator/separator.component'\n\nexport interface BackupSnapshot {\n  id: string\n  label: string\n  size: string\n  timestamp: string\n  status: 'completed' | 'in_progress' | 'failed'\n  checksum: string\n}\n\nconst initialSnapshots: BackupSnapshot[] = [\n  {\n    id: 'snap-9842',\n    label: 'Daily Scheduled Snapshot',\n    size: '14.2 GB',\n    timestamp: 'Today, 02:00 UTC',\n    status: 'completed',\n    checksum: 'sha256:7f9b...a1c3',\n  },\n  {\n    id: 'snap-9841',\n    label: 'Daily Scheduled Snapshot',\n    size: '14.1 GB',\n    timestamp: 'Yesterday, 02:00 UTC',\n    status: 'completed',\n    checksum: 'sha256:4d8e...90f2',\n  },\n  {\n    id: 'snap-9840',\n    label: 'Manual Pre-migration Checkpoint',\n    size: '13.9 GB',\n    timestamp: 'Sep 15, 14:22 UTC',\n    status: 'completed',\n    checksum: 'sha256:1a2b...3c4d',\n  },\n  {\n    id: 'snap-9839',\n    label: 'Automated Snapshot',\n    size: '13.8 GB',\n    timestamp: 'Sep 14, 02:00 UTC',\n    status: 'failed',\n    checksum: 'sha256:9e8f...5d2a',\n  },\n]\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.Eager,\n  selector: 'ui-cloud-backup-schedule, [ui-cloud-backup-schedule]',\n  standalone: true,\n  // React renders the root <div> itself: the host stays out of layout and `class` goes to the root.\n  host: { '[attr.class]': '\"contents\"' },\n  imports: [\n    LucideAngularModule,\n    UiCardComponent,\n    UiCardHeaderComponent,\n    UiCardTitleComponent,\n    UiCardDescriptionComponent,\n    UiCardContentComponent,\n    UiCardFooterComponent,\n    UiButtonComponent,\n    UiBadgeComponent,\n    UiProgressComponent,\n    UiSwitchComponent,\n    UiSeparatorComponent,\n  ],\n  template: `\n    <div [class]=\"rootClass\">\n      <!-- Main Backup Management Card -->\n      <div ui-card class=\"border-border shadow-xs\">\n        <div ui-card-header class=\"flex flex-col justify-between gap-4 pb-4 @md:flex-row @md:items-center\">\n          <div class=\"min-w-0 space-y-1\">\n            <div class=\"flex flex-wrap items-center gap-2\">\n              <div class=\"bg-primary/10 text-primary flex size-8 shrink-0 items-center justify-center rounded-lg\">\n                <lucide-icon [img]=\"Cloud\" class=\"size-4 shrink-0\" />\n              </div>\n              <h3 ui-card-title class=\"text-base font-semibold tracking-tight sm:text-lg\">\n                Cloud Backup &amp; Recovery\n              </h3>\n              <span ui-badge variant=\"outline\" class=\"border-success/20 bg-success/10 text-success shrink-0 gap-1\">\n                <lucide-icon [img]=\"ShieldCheck\" class=\"size-3 shrink-0\" />\n                AES-256\n              </span>\n            </div>\n            <p ui-card-description class=\"text-xs sm:text-sm\">\n              Automated cluster snapshot schedules, retention policies, and disaster recovery replication.\n            </p>\n          </div>\n\n          <div class=\"flex shrink-0 items-center gap-2\">\n            <button\n              ui-button\n              size=\"sm\"\n              variant=\"default\"\n              class=\"w-full cursor-pointer gap-1.5 shadow-xs @md:w-auto\"\n              [disabled]=\"isBackingUp()\"\n              (click)=\"handleTriggerBackup()\"\n            >\n              @if (isBackingUp()) {\n                <lucide-icon [img]=\"RotateCw\" class=\"size-3.5 shrink-0 animate-spin\" />\n              } @else {\n                <lucide-icon [img]=\"Play\" class=\"size-3.5 shrink-0 fill-current\" />\n              }\n              {{ isBackingUp() ? 'Snapshotting...' : 'Backup Now' }}\n            </button>\n          </div>\n        </div>\n\n        <div ui-separator></div>\n\n        <div ui-card-content class=\"grid grid-cols-1 gap-4 p-4 pt-4 sm:gap-6 sm:p-6 sm:pt-6 @md:grid-cols-2\">\n          <!-- Automation Schedule Tile -->\n          <div class=\"border-border bg-card min-w-0 space-y-4 rounded-lg border p-3.5 sm:p-4\">\n            <div class=\"flex items-center justify-between gap-2\">\n              <div class=\"flex min-w-0 items-center gap-2.5\">\n                <lucide-icon [img]=\"Clock\" class=\"text-muted-foreground size-4 shrink-0\" />\n                <span class=\"text-sm font-medium\">Daily Automation</span>\n              </div>\n              <button\n                ui-switch\n                [checked]=\"autoBackupEnabled()\"\n                (checkedChange)=\"autoBackupEnabled.set($event)\"\n                aria-label=\"Toggle daily automated backup\"\n                class=\"shrink-0\"\n              ></button>\n            </div>\n\n            <div class=\"text-muted-foreground space-y-2 text-xs\">\n              <div class=\"flex items-center justify-between gap-2\">\n                <span class=\"shrink-0\">Window:</span>\n                <span class=\"text-foreground truncate text-right font-medium\">{{ frequency }}</span>\n              </div>\n              <div class=\"flex items-center justify-between gap-2\">\n                <span class=\"shrink-0\">Retention:</span>\n                <span class=\"text-foreground truncate text-right font-medium\">{{ retentionDays }} days (rolling)</span>\n              </div>\n              <div class=\"flex items-center justify-between gap-2\">\n                <span class=\"shrink-0\">Target:</span>\n                <span class=\"text-foreground truncate text-right font-medium\">AWS S3 (us-east-1)</span>\n              </div>\n            </div>\n          </div>\n\n          <!-- Storage Quota Gauge Tile -->\n          <div class=\"border-border bg-card min-w-0 space-y-4 rounded-lg border p-3.5 sm:p-4\">\n            <div class=\"flex items-center justify-between gap-2\">\n              <div class=\"flex min-w-0 items-center gap-2\">\n                <lucide-icon [img]=\"HardDrive\" class=\"text-muted-foreground size-4 shrink-0\" />\n                <span class=\"truncate text-sm font-medium\">Vault Storage</span>\n              </div>\n              <span class=\"text-muted-foreground shrink-0 text-xs font-semibold tabular-nums\"\n                >{{ usagePercentage }}% used</span\n              >\n            </div>\n\n            <div ui-progress [value]=\"usagePercentage\" class=\"h-2\"></div>\n\n            <div class=\"text-muted-foreground flex items-center justify-between gap-2 text-xs tabular-nums\">\n              <span>{{ storageUsedGb }} GB used</span>\n              <span class=\"text-right\">{{ storageTotalGb }} GB total</span>\n            </div>\n          </div>\n        </div>\n\n        <div ui-separator></div>\n\n        <!-- Recent Snapshot Ledger -->\n        <div ui-card-content class=\"space-y-4 p-4 pt-4 sm:p-6 sm:pt-6\">\n          <div class=\"flex flex-wrap items-center justify-between gap-2\">\n            <div class=\"flex items-center gap-2\">\n              <lucide-icon [img]=\"Database\" class=\"text-muted-foreground size-4 shrink-0\" />\n              <h4 class=\"text-sm font-semibold tracking-tight\">Recent Snapshots</h4>\n            </div>\n            <span class=\"text-muted-foreground text-xs\">Last verified: {{ lastBackupSuccess() }}</span>\n          </div>\n\n          <div class=\"divide-border border-border bg-card divide-y rounded-lg border\">\n            @for (snap of snapshots(); track snap.id) {\n              <div\n                class=\"hover:bg-muted/40 flex flex-col justify-between gap-2 p-3.5 text-sm transition-colors @md:flex-row @md:items-center\"\n              >\n                <div class=\"flex min-w-0 items-center gap-3\">\n                  @if (snap.status === 'completed') {\n                    <lucide-icon [img]=\"CheckCircle2\" class=\"text-success size-4 shrink-0\" />\n                  } @else if (snap.status === 'failed') {\n                    <lucide-icon [img]=\"AlertCircle\" class=\"text-destructive size-4 shrink-0\" />\n                  } @else {\n                    <lucide-icon [img]=\"RotateCw\" class=\"text-primary size-4 shrink-0 animate-spin\" />\n                  }\n                  <div class=\"min-w-0 flex-1 space-y-0.5\">\n                    <div class=\"text-foreground flex flex-wrap items-center gap-1.5 font-medium\">\n                      <span class=\"truncate\">{{ snap.label }}</span>\n                      <span class=\"text-muted-foreground shrink-0 font-mono text-xs\">({{ snap.id }})</span>\n                    </div>\n                    <div class=\"text-muted-foreground flex items-center gap-2 font-mono text-xs\">\n                      <span class=\"truncate font-mono\">{{ snap.checksum }}</span>\n                      <span class=\"shrink-0\">•</span>\n                      <span class=\"shrink-0\">{{ snap.size }}</span>\n                    </div>\n                  </div>\n                </div>\n\n                <div class=\"flex shrink-0 items-center justify-between gap-3 pl-7 @md:justify-end @md:pl-0\">\n                  <span class=\"text-muted-foreground text-xs whitespace-nowrap\">{{ snap.timestamp }}</span>\n                  <span\n                    ui-badge\n                    [variant]=\"statusVariant(snap.status)\"\n                    class=\"shrink-0 text-xs whitespace-nowrap capitalize\"\n                    >{{ statusLabel(snap.status) }}</span\n                  >\n                </div>\n              </div>\n            }\n          </div>\n        </div>\n\n        <div\n          ui-card-footer\n          class=\"border-border text-muted-foreground flex flex-col items-start justify-between gap-3 border-t pt-4 text-xs @md:flex-row @md:items-center\"\n        >\n          <div class=\"flex items-center gap-2\">\n            <lucide-icon [img]=\"Calendar\" class=\"size-3.5 shrink-0\" />\n            <span>Next scheduled backup: Tonight at 02:00 UTC</span>\n          </div>\n          <a\n            href=\"#docs\"\n            class=\"text-primary inline-flex shrink-0 items-center gap-1 font-medium hover:underline\"\n            (click)=\"$event.preventDefault()\"\n            >Disaster recovery runbook<lucide-icon [img]=\"ArrowUpRight\" class=\"size-3 shrink-0\"\n          /></a>\n        </div>\n      </div>\n    </div>\n  `,\n})\nexport class UiCloudBackupScheduleComponent implements OnInit {\n  @Input() initialAutoBackup = true\n  @Input() frequency = 'Everyday at 02:00 UTC'\n  @Input() retentionDays = 30\n  @Input() storageUsedGb = 68.4\n  @Input() storageTotalGb = 100\n  @Input('class') className?: string\n\n  readonly autoBackupEnabled = signal(true)\n  readonly isBackingUp = signal(false)\n  readonly lastBackupSuccess = signal('12 minutes ago')\n  readonly snapshots = signal<BackupSnapshot[]>(initialSnapshots.map((s) => ({ ...s })))\n\n  protected readonly AlertCircle = AlertCircle\n  protected readonly ArrowUpRight = ArrowUpRight\n  protected readonly Calendar = Calendar\n  protected readonly CheckCircle2 = CheckCircle2\n  protected readonly Clock = Clock\n  protected readonly Cloud = Cloud\n  protected readonly Database = Database\n  protected readonly HardDrive = HardDrive\n  protected readonly Play = Play\n  protected readonly RotateCw = RotateCw\n  protected readonly ShieldCheck = ShieldCheck\n\n  private timer: ReturnType<typeof setTimeout> | undefined\n\n  constructor() {\n    inject(DestroyRef).onDestroy(() => clearTimeout(this.timer))\n  }\n\n  // React seeds useState from the prop once; inputs are only bound by ngOnInit.\n  ngOnInit(): void {\n    this.autoBackupEnabled.set(this.initialAutoBackup)\n  }\n\n  get rootClass(): string {\n    return cn('@container w-full max-w-4xl space-y-6', this.className)\n  }\n\n  get usagePercentage(): number {\n    return Math.round((this.storageUsedGb / this.storageTotalGb) * 100)\n  }\n\n  statusVariant(status: BackupSnapshot['status']): BadgeVariant {\n    return status === 'completed' ? 'secondary' : status === 'failed' ? 'destructive' : 'outline'\n  }\n\n  statusLabel(status: BackupSnapshot['status']): string {\n    return status.replace('_', ' ')\n  }\n\n  handleTriggerBackup(): void {\n    if (this.isBackingUp()) return\n    this.isBackingUp.set(true)\n\n    this.timer = setTimeout(() => {\n      this.isBackingUp.set(false)\n      this.lastBackupSuccess.set('Just now')\n      this.snapshots.update((prev) => [\n        {\n          id: `snap-${Math.floor(1000 + Math.random() * 9000)}`,\n          label: 'Manual On-demand Snapshot',\n          size: '14.3 GB',\n          timestamp: 'Just now',\n          status: 'completed',\n          checksum: `sha256:${Math.random().toString(36).substring(2, 6)}...${Math.random().toString(36).substring(2, 6)}`,\n        },\n        ...prev,\n      ])\n    }, 1200)\n  }\n}\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/cloud-backup-schedule/cloud-backup-schedule.component.ts"
    },
    {
      "path": "packages/registry-angular/blocks/cloud-backup-schedule/index.ts",
      "content": "export { UiCloudBackupScheduleComponent, type BackupSnapshot } from './cloud-backup-schedule.component'\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/cloud-backup-schedule/index.ts"
    }
  ],
  "dependencies": [
    "lucide-angular"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/angular/card.json",
    "https://uipkge.dev/r/angular/button.json",
    "https://uipkge.dev/r/angular/badge.json",
    "https://uipkge.dev/r/angular/progress.json",
    "https://uipkge.dev/r/angular/switch.json",
    "https://uipkge.dev/r/angular/separator.json"
  ],
  "description": "Automated cloud snapshot scheduler with storage quota metering, encryption status, and recent snapshot timeline.",
  "categories": [
    "dashboard",
    "devops",
    "data"
  ]
}