master
Raw Download raw file
 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};