115 lines
2.9 KiB
TypeScript
115 lines
2.9 KiB
TypeScript
import useSWR from "swr";
|
|
|
|
// API response interface (what we receive from the server)
|
|
type ApiUserResponse = {
|
|
uuid: string;
|
|
username: string;
|
|
displayname?: string;
|
|
public_key: string;
|
|
private_key_hash: string;
|
|
avatar?: string;
|
|
storage: number;
|
|
connected: boolean;
|
|
createdAt: number;
|
|
};
|
|
|
|
// User interface (what we use in the UI - includes computed displayName)
|
|
interface User extends ApiUserResponse {
|
|
displayName: string; // Always provided by our processing
|
|
}
|
|
|
|
// SWR fetcher function
|
|
const fetcher = (url: string) => fetch(url).then((res) => res.json());
|
|
|
|
// Custom hook for checking username availability
|
|
export const useUsernameAvailability = (username: string) => {
|
|
const shouldFetch = username && username.length >= 3;
|
|
const { data, error, isLoading } = useSWR(
|
|
shouldFetch ? `https://omega.tensamin.net/api/get/id/${username}` : null,
|
|
fetcher,
|
|
{
|
|
revalidateOnFocus: false,
|
|
dedupingInterval: 5000, // Cache for 5 seconds
|
|
},
|
|
);
|
|
|
|
return {
|
|
isAvailable: data?.type === "error", // "error" means username is available
|
|
isTaken: data?.type === "success", // "success" means username is taken
|
|
isLoading,
|
|
error,
|
|
};
|
|
};
|
|
|
|
// Custom hook for getting users list
|
|
export const useUsers = () => {
|
|
const {
|
|
data,
|
|
error,
|
|
isLoading,
|
|
mutate: refreshUsers,
|
|
} = useSWR("/api/users/get/", fetcher, {
|
|
revalidateOnFocus: false,
|
|
dedupingInterval: 30000, // Cache for 30 seconds
|
|
});
|
|
|
|
// Process the API response to ensure UI compatibility
|
|
// Check if data is an array before processing
|
|
const processedUsers = (Array.isArray(data) ? data : []).map(
|
|
(user: ApiUserResponse) => ({
|
|
...user,
|
|
displayName: user.displayname || user.username, // Always provide displayName for UI
|
|
}),
|
|
) as User[];
|
|
|
|
// Wrapper function that only resolves if refresh succeeds
|
|
const refreshUsersWithPromise = async () => {
|
|
try {
|
|
const result = await refreshUsers();
|
|
// Check if the result is valid (array of users)
|
|
if (!Array.isArray(result)) {
|
|
throw new Error("Failed to load users");
|
|
}
|
|
return result;
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
};
|
|
|
|
// Function to delete a user
|
|
const deleteUser = async (uuid: string) => {
|
|
try {
|
|
const response = await fetch("/api/users/remove/", {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
},
|
|
body: JSON.stringify({ uuid }),
|
|
});
|
|
|
|
if (!response.ok) {
|
|
throw new Error("Failed to delete user");
|
|
}
|
|
|
|
const result = await response.json();
|
|
|
|
// Refresh the users list after successful deletion
|
|
await refreshUsersWithPromise();
|
|
|
|
return result;
|
|
} catch (error) {
|
|
throw error;
|
|
}
|
|
};
|
|
|
|
return {
|
|
users: processedUsers,
|
|
isLoading,
|
|
error,
|
|
refreshUsers: refreshUsersWithPromise,
|
|
deleteUser,
|
|
};
|
|
};
|
|
|
|
// Export User type for other components to use
|
|
export type { User };
|