SidebarHint.tsx raw

   1  import {
   2    HeartIcon,
   3    ListTodoIcon,
   4    LucideIcon,
   5    XIcon,
   6    ZapIcon,
   7  } from "lucide-react";
   8  import React, { ReactElement } from "react";
   9  import { useLocation } from "react-router";
  10  import { toast } from "sonner";
  11  import {
  12    Card,
  13    CardContent,
  14    CardHeader,
  15    CardTitle,
  16  } from "src/components/ui/card";
  17  import { LinkButton } from "src/components/ui/custom/link-button";
  18  import { Progress } from "src/components/ui/progress";
  19  import { localStorageKeys, SUPPORT_ALBY_CONNECTION_NAME } from "src/constants";
  20  import { useAlbyMe } from "src/hooks/useAlbyMe";
  21  import { useApps } from "src/hooks/useApps";
  22  import { useOnboardingData } from "src/hooks/useOnboardingData";
  23  import useChannelOrderStore from "src/state/ChannelOrderStore";
  24  
  25  function SidebarHint() {
  26    const { isLoading, checklistItems } = useOnboardingData();
  27    const { data: supportAlbyAppsData } = useApps(undefined, undefined, {
  28      name: SUPPORT_ALBY_CONNECTION_NAME,
  29    });
  30    const { data: albyMe } = useAlbyMe();
  31    const { order } = useChannelOrderStore();
  32    const location = useLocation();
  33  
  34    const [hiddenUntil, setHiddenUntil] = React.useState(
  35      localStorage.getItem(localStorageKeys.supportAlbySidebarHintHiddenUntil)
  36    );
  37  
  38    // User has a channel order
  39    if (
  40      !location.pathname.startsWith("/channels/") &&
  41      order &&
  42      order.status !== "pay"
  43    ) {
  44      return (
  45        <SidebarHintCard
  46          icon={ZapIcon}
  47          title="New Channel"
  48          description="You're currently opening a new channel"
  49          buttonText="View Channel"
  50          buttonLink="/channels/order"
  51        />
  52      );
  53    }
  54  
  55    const openChecklistItems = checklistItems.filter((x) => !x.checked);
  56    if (
  57      !location.pathname.startsWith("/home") &&
  58      !location.pathname.startsWith("/channels/order") &&
  59      !location.pathname.startsWith("/channels/first") &&
  60      !isLoading &&
  61      openChecklistItems.length
  62    ) {
  63      return (
  64        <SidebarHintCard
  65          icon={ListTodoIcon}
  66          title="Finish Setup"
  67          description={
  68            <>
  69              <Progress
  70                className="mt-2"
  71                value={
  72                  ((checklistItems.length - openChecklistItems.length) /
  73                    checklistItems.length) *
  74                  100
  75                }
  76              />
  77              <div className="text-xs mt-2">
  78                {checklistItems.length - openChecklistItems.length} out of{" "}
  79                {checklistItems.length} completed
  80              </div>
  81            </>
  82          }
  83          buttonText="See Next Steps"
  84          buttonLink="/home"
  85        />
  86      );
  87    }
  88  
  89    const showSupport =
  90      supportAlbyAppsData &&
  91      supportAlbyAppsData.apps.length === 0 &&
  92      !albyMe?.subscription.plan_code;
  93  
  94    if (
  95      !location.pathname.startsWith("/support-alby") &&
  96      showSupport &&
  97      (!hiddenUntil || new Date() >= new Date(hiddenUntil))
  98    ) {
  99      return (
 100        <SidebarHintCard
 101          onClose={() => {
 102            // Set the date to the next 21st of the month
 103            const now = new Date();
 104            const next21st = new Date(
 105              now.getFullYear(),
 106              now.getMonth() + (now.getDate() >= 21 ? 1 : 0),
 107              21
 108            ).toString();
 109            localStorage.setItem(
 110              localStorageKeys.supportAlbySidebarHintHiddenUntil,
 111              next21st
 112            );
 113            setHiddenUntil(next21st);
 114            toast("No worries, we'll remind you again!");
 115          }}
 116          icon={HeartIcon}
 117          title="Support Alby Hub"
 118          description="See how you can support the development of Alby Hub"
 119          buttonText="Become a Supporter"
 120          buttonLink="/support-alby"
 121        />
 122      );
 123    }
 124  }
 125  
 126  type SidebarHintCardProps = {
 127    title: string;
 128    description: string | ReactElement;
 129    buttonText: string;
 130    buttonLink: string;
 131    icon: LucideIcon;
 132    onClose?: () => void;
 133  };
 134  function SidebarHintCard({
 135    title,
 136    description,
 137    icon: Icon,
 138    buttonText,
 139    buttonLink,
 140    onClose,
 141  }: SidebarHintCardProps) {
 142    return (
 143      <Card className="gap-3">
 144        <CardHeader>
 145          <Icon className="h-8 w-8 mb-2" />
 146          <CardTitle>{title}</CardTitle>
 147          {onClose && (
 148            <button
 149              className="absolute top-6 right-6 text-muted-foreground hover:text-foreground"
 150              onClick={onClose}
 151            >
 152              <XIcon className="size-4" />
 153            </button>
 154          )}
 155        </CardHeader>
 156        <CardContent className="flex flex-col gap-3">
 157          <div className="text-muted-foreground text-sm">{description}</div>
 158          <LinkButton to={buttonLink} size="sm" className="w-full">
 159            {buttonText}
 160          </LinkButton>
 161        </CardContent>
 162      </Card>
 163    );
 164  }
 165  
 166  export default SidebarHint;
 167