| 1 | import { CircleCheckIcon } from "lucide-react"; |
| 2 | import type { ComponentProps, ReactNode } from "react"; |
| 3 | import { Button } from "../ui/button"; |
| 4 | |
| 5 | export interface PermissionItem { |
| 6 | id: string; |
| 7 | icon: ReactNode; |
| 8 | title: string; |
| 9 | description: string; |
| 10 | granted: boolean; |
| 11 | onAllow: () => void; |
| 12 | } |
| 13 | |
| 14 | export function PermissionChecklist({ |
| 15 | permissions, |
| 16 | busy = false, |
| 17 | }: { |
| 18 | permissions: readonly PermissionItem[]; |
| 19 | busy?: boolean; |
| 20 | }) { |
| 21 | return ( |
| 22 | <div className="space-y-2"> |
| 23 | {permissions.map((permission) => ( |
| 24 | <div key={permission.id} className="flex items-center gap-3 rounded-lg border px-3 py-2"> |
| 25 | {permission.icon} |
| 26 | <div className="min-w-0 flex-1"> |
| 27 | <p className="font-medium">{permission.title}</p> |
| 28 | <p className="text-xs text-muted-foreground">{permission.description}</p> |
| 29 | </div> |
| 30 | {permission.granted ? ( |
| 31 | <span role="status" className="flex items-center gap-1 text-xs text-success"> |
| 32 | <CircleCheckIcon className="size-4" aria-hidden="true" /> |
| 33 | Allowed |
| 34 | </span> |
| 35 | ) : ( |
| 36 | <Button size="xs" variant="outline" disabled={busy} onClick={permission.onAllow}> |
| 37 | Allow |
| 38 | </Button> |
| 39 | )} |
| 40 | </div> |
| 41 | ))} |
| 42 | </div> |
| 43 | ); |
| 44 | } |
| 45 | |
| 46 | export function PermissionContinueButton({ |
| 47 | ready, |
| 48 | busy = false, |
| 49 | children = "Continue", |
| 50 | ...props |
| 51 | }: Omit<ComponentProps<typeof Button>, "disabled"> & { ready: boolean; busy?: boolean }) { |
| 52 | return ( |
| 53 | <Button {...props} disabled={!ready || busy}> |
| 54 | {children} |
| 55 | </Button> |
| 56 | ); |
| 57 | } |