-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathuse-credentials.ts
More file actions
66 lines (59 loc) · 1.67 KB
/
Copy pathuse-credentials.ts
File metadata and controls
66 lines (59 loc) · 1.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
import { useState, useCallback, useMemo } from "react";
import { useFetch } from "./use-fetch";
import {
fetchCredentials,
createCredential,
deleteCredential,
} from "@/api/endpoints/credentials";
import type { Credential, CreateCredentialPayload } from "@/api/types";
interface UseCredentialsReturn {
credentials: Credential[];
loading: boolean;
error: Error | null;
add: (payload: CreateCredentialPayload) => Promise<boolean>;
remove: (id: string) => Promise<void>;
refetch: () => void;
}
export function useCredentials(): UseCredentialsReturn {
const { data, loading, error, refetch } = useFetch(fetchCredentials);
const [optimisticRemoved, setOptimisticRemoved] = useState<Set<string>>(
new Set(),
);
const credentials = useMemo(() => {
if (!data) return [];
return data.credentials
.filter((c) => !optimisticRemoved.has(c.id))
.sort(
(a, b) =>
new Date(b.created_at).getTime() - new Date(a.created_at).getTime(),
);
}, [data, optimisticRemoved]);
const add = useCallback(
async (payload: CreateCredentialPayload): Promise<boolean> => {
try {
await createCredential(payload);
refetch();
return true;
} catch {
return false;
}
},
[refetch],
);
const remove = useCallback(
async (id: string) => {
setOptimisticRemoved((prev) => new Set(prev).add(id));
try {
await deleteCredential(id);
} catch {
setOptimisticRemoved((prev) => {
const next = new Set(prev);
next.delete(id);
return next;
});
}
},
[],
);
return { credentials, loading, error, add, remove, refetch };
}