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