master
1import { DateTime } from "luxon";
2import React from "react";
3
4import { useUser } from "./useUser";
5
6interface Secret {
7 id: string;
8 name: string;
9 createdAt: string;
10 revealAt: string;
11}
12
13interface MySecretsContextValue {
14 secrets: {
15 loading: boolean;
16 value?: Secret[];
17 };
18 createSecret: (name: string, secret: string, revealAt: DateTime) => Promise<string>;
19}
20
21const MySecretsContext = React.createContext<MySecretsContextValue | undefined>(undefined);
22
23export const MySecretsProvider = ({ children }: { children: React.ReactNode }) => {
24 const { user } = useUser();
25 const [secrets, setSecrets] = React.useState<MySecretsContextValue["secrets"]>({ loading: true });
26
27 const refresh = React.useCallback(async () => {
28 if (user.loading) {
29 setSecrets({ loading: true });
30 return;
31 }
32
33 if (user.value === undefined) {
34 setSecrets({ loading: false });
35 return;
36 }
37
38 setSecrets({ loading: true });
39 const res = await fetch("/api/secrets/my");
40 if (res.ok) {
41 const { secrets } = await res.json();
42 setSecrets({ loading: false, value: secrets });
43 } else {
44 setSecrets({ loading: false });
45 }
46 }, [user]);
47
48 const createSecret = React.useCallback(
49 async (name: string, secret: string, revealAt: DateTime) => {
50 const res = await fetch("/api/secrets/create", {
51 method: "POST",
52 headers: {
53 "Content-Type": "application/json",
54 },
55 body: JSON.stringify({
56 name,
57 secret,
58 revealAt: revealAt.setZone("UTC").toISO(),
59 }),
60 });
61
62 if (res.ok) {
63 await refresh();
64 const json = await res.json();
65 return json.id;
66 } else {
67 throw new Error("Failed to create secret");
68 }
69 },
70 [refresh],
71 );
72
73 React.useEffect(() => {
74 refresh();
75 }, [refresh]);
76
77 return <MySecretsContext.Provider value={{ secrets, createSecret }}>{children}</MySecretsContext.Provider>;
78};
79
80export const useMySecrets = () => {
81 const context = React.useContext(MySecretsContext);
82 if (context === undefined) {
83 throw new Error("useMySecrets must be used within a MySecretsProvider");
84 }
85 return context;
86};