feat: add useAuth hook and login page
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
97
src/client/hooks/useAuth.ts
Normal file
97
src/client/hooks/useAuth.ts
Normal file
@@ -0,0 +1,97 @@
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import { apiDelete, apiGet, apiPost, apiPut } from "../lib/api";
|
||||
|
||||
interface AuthState {
|
||||
user: { id: number } | null;
|
||||
setupRequired: boolean;
|
||||
}
|
||||
|
||||
export function useAuth() {
|
||||
return useQuery({
|
||||
queryKey: ["auth"],
|
||||
queryFn: () => apiGet<AuthState>("/api/auth/me"),
|
||||
staleTime: 5 * 60 * 1000,
|
||||
});
|
||||
}
|
||||
|
||||
export function useLogin() {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: (data: { username: string; password: string }) =>
|
||||
apiPost<{ username: string }>("/api/auth/login", data),
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ["auth"] });
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useLogout() {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: () => apiPost<{ success: boolean }>("/api/auth/logout", {}),
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ["auth"] });
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useSetup() {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: (data: { username: string; password: string }) =>
|
||||
apiPost<{ username: string }>("/api/auth/setup", data),
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ["auth"] });
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useChangePassword() {
|
||||
return useMutation({
|
||||
mutationFn: (data: { currentPassword: string; newPassword: string }) =>
|
||||
apiPut<{ success: boolean }>("/api/auth/password", data),
|
||||
});
|
||||
}
|
||||
|
||||
interface ApiKeyListItem {
|
||||
id: number;
|
||||
name: string;
|
||||
keyPrefix: string;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
interface ApiKeyResponse {
|
||||
id: number;
|
||||
name: string;
|
||||
key: string;
|
||||
prefix: string;
|
||||
}
|
||||
|
||||
export function useApiKeys() {
|
||||
return useQuery({
|
||||
queryKey: ["apiKeys"],
|
||||
queryFn: () => apiGet<ApiKeyListItem[]>("/api/auth/keys"),
|
||||
});
|
||||
}
|
||||
|
||||
export function useCreateApiKey() {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: (data: { name: string }) =>
|
||||
apiPost<ApiKeyResponse>("/api/auth/keys", data),
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ["apiKeys"] });
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useDeleteApiKey() {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: (id: number) =>
|
||||
apiDelete<{ success: boolean }>(`/api/auth/keys/${id}`),
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ["apiKeys"] });
|
||||
},
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user