fix(hackathon): fix team leader access denied and member removal

- Add loading state check before leader validation to prevent race condition
- Fix useRemoveMember hook to use Supabase directly instead of missing API endpoint
- Leader check now waits for team data to load before showing Access Denied

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Maulana Sodiqin
2025-11-26 15:36:35 +07:00
co-authored by Claude
parent 1839f4cab0
commit 62780c8889
2 changed files with 50 additions and 2 deletions
@@ -23,7 +23,7 @@ const ManageMembersPage: FC = (): ReactElement => {
const { session } = useAuthStore();
const [showInviteModal, setShowInviteModal] = useState(false);
const { data: teamData } = useTeamById(teamId || '');
const { data: teamData, isLoading: isLoadingTeam } = useTeamById(teamId || '');
const { data: membersData, isLoading: isLoadingMembers } = useTeamMembers(teamId || '');
const { data: joinRequestsData } = useTeamJoinRequests(teamId || '');
@@ -42,6 +42,15 @@ const ManageMembersPage: FC = (): ReactElement => {
mode: 'all',
});
// Show loading state while fetching team data
if (isLoadingTeam) {
return (
<div className="flex flex-col items-center justify-center min-h-screen">
<p className="text-gray-600">Loading...</p>
</div>
);
}
if (!isLeader) {
return (
<div className="flex flex-col items-center justify-center min-h-screen">
+40 -1
View File
@@ -312,9 +312,48 @@ export const useManageMember = (teamId: string) => {
export const useRemoveMember = (teamId: string) => {
const queryClient = useQueryClient();
const { session } = useAuthStore();
return useMutation({
mutationFn: (userId: string) => teamsApi.removeMember(teamId, userId),
mutationFn: async (userId: string) => {
if (!session?.user?.id) {
throw new Error('You must be logged in to remove a member');
}
// Verify the current user is the team leader
const { data: team, error: teamError } = await supabase
.from('teams')
.select('leader_id')
.eq('id', teamId)
.single();
if (teamError || !team) {
throw new Error('Team not found');
}
if (team.leader_id !== session.user.id) {
throw new Error('Only the team leader can remove members');
}
// Cannot remove the leader
if (userId === team.leader_id) {
throw new Error('Cannot remove the team leader');
}
// Delete the team member record
const { error: deleteError } = await supabase
.from('team_members')
.delete()
.eq('team_id', teamId)
.eq('user_id', userId);
if (deleteError) {
console.error('Failed to remove member:', deleteError);
throw new Error(deleteError.message || 'Failed to remove member');
}
return { success: true };
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: teamKeys.members(teamId) });
queryClient.invalidateQueries({ queryKey: teamKeys.detail(teamId) });