tangled
alpha
login
or
join now
yoginth.com
/
hey
1
fork
atom
Hey is a decentralized and permissionless social media app built with Lens Protocol 🌿
1
fork
atom
overview
issues
pulls
pipelines
Remove API
yoginth.com
6 months ago
68224e34
115bfb59
+1
-117
3 changed files
expand all
collapse all
unified
split
apps
web
src
components
Pages
App.tsx
helpers
fetcher.ts
routes.tsx
-103
apps/web/src/components/Pages/App.tsx
···
1
1
-
import { useMutation, useQuery } from "@tanstack/react-query";
2
2
-
import { memo } from "react";
3
3
-
import { toast } from "sonner";
4
4
-
import { z } from "zod";
5
5
-
import PageLayout from "@/components/Shared/PageLayout";
6
6
-
import { Button, Card, Form, H3, useZodForm } from "@/components/Shared/UI";
7
7
-
import errorToast from "@/helpers/errorToast";
8
8
-
import { hono } from "@/helpers/fetcher";
9
9
-
import { useProModalStore } from "@/store/non-persisted/modal/useProModalStore";
10
10
-
import { useAccountStore } from "@/store/persisted/useAccountStore";
11
11
-
12
12
-
interface AppEnrollFormValues {
13
13
-
email: string;
14
14
-
}
15
15
-
16
16
-
const schema = z.object({
17
17
-
email: z.string().email("Enter a valid email address")
18
18
-
});
19
19
-
20
20
-
const App = () => {
21
21
-
const { currentAccount } = useAccountStore();
22
22
-
const { setShow: setShowProModal } = useProModalStore();
23
23
-
24
24
-
const form = useZodForm<typeof schema>({ schema });
25
25
-
26
26
-
const { data, refetch } = useQuery({
27
27
-
queryFn: () => hono.app.getStatus(),
28
28
-
queryKey: ["app-status"]
29
29
-
});
30
30
-
31
31
-
const { mutate, isPending } = useMutation({
32
32
-
mutationFn: ({ email }: { email: string }) => hono.app.request(email),
33
33
-
onError: errorToast,
34
34
-
onSuccess: async () => {
35
35
-
await refetch();
36
36
-
toast.success("You're on the list! We'll email you when it's ready.");
37
37
-
}
38
38
-
});
39
39
-
40
40
-
const handleOpenPro = () => setShowProModal(true);
41
41
-
42
42
-
const handleRequest = async (values: AppEnrollFormValues) => {
43
43
-
mutate({ email: values.email });
44
44
-
};
45
45
-
46
46
-
return (
47
47
-
<PageLayout title="Mobile App Early Access" zeroTopMargin>
48
48
-
<div className="mx-auto h-screen rounded-none bg-gradient-to-tr from-cyan-800 via-blue-800 to-indigo-900 p-8 shadow-lg md:h-fit md:rounded-2xl">
49
49
-
<H3 className="font-bold text-2xl text-white">Join the waitlist</H3>
50
50
-
<p className="mt-3 text-white/90 leading-relaxed">
51
51
-
Be the first to try the Hey mobile app. Submit your email and we'll
52
52
-
notify you as soon as early access is available.
53
53
-
</p>
54
54
-
{currentAccount?.hasSubscribed ? (
55
55
-
data?.requested ? (
56
56
-
<div className="mt-5 rounded-lg bg-white/10 px-5 py-3 text-center font-medium text-white">
57
57
-
You're on the list ✅
58
58
-
</div>
59
59
-
) : (
60
60
-
<Card
61
61
-
className="mt-5 overflow-hidden border-none p-0 shadow-sm"
62
62
-
forceRounded
63
63
-
>
64
64
-
<Form<AppEnrollFormValues> form={form} onSubmit={handleRequest}>
65
65
-
<div className="flex flex-col sm:flex-row">
66
66
-
<input
67
67
-
aria-label="Email address"
68
68
-
className="flex-1 rounded-none border-0 px-4 py-3 focus:ring-0 sm:rounded-l-xl"
69
69
-
placeholder="you@example.com"
70
70
-
type="email"
71
71
-
{...form.register("email")}
72
72
-
/>
73
73
-
<Button
74
74
-
aria-label="Request early access"
75
75
-
className="rounded-none px-6 sm:rounded-r-xl"
76
76
-
loading={isPending}
77
77
-
type="submit"
78
78
-
>
79
79
-
Request
80
80
-
</Button>
81
81
-
</div>
82
82
-
</Form>
83
83
-
</Card>
84
84
-
)
85
85
-
) : null}
86
86
-
87
87
-
<div className="mt-4 rounded-lg bg-white/10 p-3 text-sm text-white/90">
88
88
-
Early access is available only for <b>Hey Pro</b> subscribers. If
89
89
-
you're not subscribed yet, you can get priority access by{" "}
90
90
-
<button
91
91
-
className="ml-1 underline hover:text-yellow-200"
92
92
-
onClick={handleOpenPro}
93
93
-
type="button"
94
94
-
>
95
95
-
subscribing to Pro
96
96
-
</button>
97
97
-
</div>
98
98
-
</div>
99
99
-
</PageLayout>
100
100
-
);
101
101
-
};
102
102
-
103
103
-
export default memo(App);
+1
-12
apps/web/src/helpers/fetcher.ts
···
1
1
import { HEY_API_URL } from "@hey/data/constants";
2
2
import { Status } from "@hey/data/enums";
3
3
-
import type { AppStatus, Oembed, STS } from "@hey/types/api";
3
3
+
import type { Oembed, STS } from "@hey/types/api";
4
4
import { hydrateAuthTokens } from "@/store/persisted/useAuthStore";
5
5
import { isTokenExpiringSoon, refreshTokens } from "./tokenManager";
6
6
···
62
62
};
63
63
64
64
export const hono = {
65
65
-
app: {
66
66
-
getStatus: (): Promise<AppStatus> => {
67
67
-
return fetchApi<AppStatus>("/app/get", { method: "GET" });
68
68
-
},
69
69
-
request: (email: string): Promise<AppStatus> => {
70
70
-
return fetchApi<AppStatus>("/app/request", {
71
71
-
body: JSON.stringify({ email }),
72
72
-
method: "POST"
73
73
-
});
74
74
-
}
75
75
-
},
76
65
metadata: {
77
66
sts: (): Promise<STS> => {
78
67
return fetchApi<STS>("/metadata/sts", { method: "GET" });
-2
apps/web/src/routes.tsx
···
28
28
import SessionsSettings from "@/components/Settings/Sessions";
29
29
import UsernameSettings from "@/components/Settings/Username";
30
30
import Custom404 from "@/components/Shared/404";
31
31
-
import App from "./components/Pages/App";
32
31
import RewardsSettings from "./components/Settings/Rewards";
33
32
import Staff from "./components/Staff";
34
33
···
79
78
<Route path="staff">
80
79
<Route element={<Staff />} index />
81
80
</Route>
82
82
-
<Route element={<App />} path="app" />
83
81
<Route element={<Support />} path="support" />
84
82
<Route element={<Terms />} path="terms" />
85
83
<Route element={<Privacy />} path="privacy" />