fiddy/apps/web/hooks/use-group-members.ts
2026-02-11 23:45:15 -08:00

137 lines
3.8 KiB
TypeScript

import { useCallback, useEffect, useState } from "react";
import type { ApiResult } from "@/lib/client/fetch-json";
import {
groupMembersApprove,
groupMembersDemote,
groupMembersKick,
groupMembersLeave,
groupMembersList,
groupMembersPromote,
groupMembersTransferOwner,
groupMembersDeny,
type GroupMember,
type JoinRequest
} from "@/lib/client/group-members";
function isError<T>(result: ApiResult<T>): result is { error: { code: string; message: string } } {
return "error" in result;
}
export default function useGroupMembers(activeGroupId?: number | null) {
const [members, setMembers] = useState<GroupMember[]>([]);
const [requests, setRequests] = useState<JoinRequest[]>([]);
const [currentUserId, setCurrentUserId] = useState<number | null>(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState("");
const load = useCallback(async () => {
if (!activeGroupId) {
setMembers([]);
setRequests([]);
setCurrentUserId(null);
setError("");
return;
}
setLoading(true);
setError("");
const result = await groupMembersList();
if (isError(result)) {
setError(result.error.message || "");
} else {
setMembers(result.data.members || []);
setRequests(result.data.requests || []);
setCurrentUserId(result.data.currentUserId || null);
}
setLoading(false);
}, [activeGroupId]);
const approve = useCallback(async (userId: number, requestId?: number) => {
const result = await groupMembersApprove({ userId, requestId });
if (isError(result)) {
setError(result.error.message || "");
return false;
}
await load();
return true;
}, [load]);
const deny = useCallback(async (userId: number) => {
const result = await groupMembersDeny({ userId });
if (isError(result)) {
setError(result.error.message || "");
return false;
}
await load();
return true;
}, [load]);
const kick = useCallback(async (userId: number) => {
const result = await groupMembersKick({ userId });
if (isError(result)) {
setError(result.error.message || "");
return false;
}
await load();
return true;
}, [load]);
const promote = useCallback(async (userId: number) => {
const result = await groupMembersPromote({ userId });
if (isError(result)) {
setError(result.error.message || "");
return false;
}
await load();
return true;
}, [load]);
const demote = useCallback(async (userId: number) => {
const result = await groupMembersDemote({ userId });
if (isError(result)) {
setError(result.error.message || "");
return false;
}
await load();
return true;
}, [load]);
const transferOwner = useCallback(async (userId: number) => {
const result = await groupMembersTransferOwner({ userId });
if (isError(result)) {
setError(result.error.message || "");
return false;
}
await load();
return true;
}, [load]);
const leave = useCallback(async () => {
const result = await groupMembersLeave();
if (isError(result)) {
setError(result.error.message || "");
return false;
}
return true;
}, []);
useEffect(() => {
load();
}, [load]);
return {
members,
requests,
currentUserId,
loading,
error,
approve,
deny,
kick,
promote,
demote,
transferOwner,
leave,
reload: load
};
}