OnboardingChecklist.tsx raw

   1  import { ChevronRightIcon, CircleCheckIcon, CircleIcon } from "lucide-react";
   2  import { Link } from "react-router";
   3  import {
   4    Card,
   5    CardContent,
   6    CardDescription,
   7    CardHeader,
   8    CardTitle,
   9  } from "src/components/ui/card";
  10  import { useOnboardingData } from "src/hooks/useOnboardingData";
  11  import { cn } from "src/lib/utils";
  12  
  13  interface ChecklistItemProps {
  14    title: string;
  15    checked: boolean;
  16    description: string;
  17    to: string;
  18    disabled: boolean;
  19    index: number;
  20  }
  21  
  22  function OnboardingChecklist() {
  23    const { isLoading, checklistItems } = useOnboardingData();
  24  
  25    if (isLoading || !checklistItems.find((x) => !x.checked)) {
  26      return null;
  27    }
  28  
  29    return (
  30      <Card>
  31        <CardHeader>
  32          <CardTitle>Get started with your Alby Hub</CardTitle>
  33          <CardDescription>
  34            Follow these initial steps to set up and make the most of your Alby
  35            Hub.
  36          </CardDescription>
  37        </CardHeader>
  38        <CardContent className="flex flex-col">
  39          {checklistItems.map((item, index) => (
  40            <ChecklistItem
  41              key={item.title}
  42              index={index}
  43              title={item.title}
  44              description={item.description}
  45              checked={item.checked}
  46              to={item.to}
  47              disabled={item.disabled}
  48            />
  49          ))}
  50        </CardContent>
  51      </Card>
  52    );
  53  }
  54  
  55  function ChecklistItem({
  56    title,
  57    checked = false,
  58    description,
  59    to,
  60    disabled = false,
  61    index,
  62  }: ChecklistItemProps) {
  63    const content = (
  64      <div
  65        className={cn(
  66          "flex flex-col p-3 relative group rounded-lg",
  67          !checked && !disabled && "hover:bg-muted",
  68          disabled && "opacity-50"
  69        )}
  70      >
  71        {!checked && !disabled && (
  72          <div className="absolute top-0 left-0 w-full h-full items-center justify-end pr-1.5 hidden group-hover:flex opacity-25">
  73            <ChevronRightIcon className="size-8" />
  74          </div>
  75        )}
  76        <div className="flex items-center gap-2">
  77          {checked ? (
  78            <CircleCheckIcon className="size-5" />
  79          ) : (
  80            <CircleIcon className="size-5" />
  81          )}
  82          <div
  83            className={cn(
  84              "text-sm font-medium leading-none",
  85              checked && "line-through"
  86            )}
  87          >
  88            {index + 1}. {title}
  89          </div>
  90        </div>
  91        {!checked && (
  92          <div className="text-muted-foreground text-sm mx-7">{description}</div>
  93        )}
  94      </div>
  95    );
  96  
  97    return checked || disabled ? content : <Link to={to}>{content}</Link>;
  98  }
  99  
 100  export default OnboardingChecklist;
 101