feat: Execute production readiness plan

This commit is contained in:
gpt-engineer-app[bot]
2025-10-20 13:41:54 +00:00
parent 368b97da04
commit 7f425ecb94
10 changed files with 108 additions and 141 deletions

View File

@@ -9,7 +9,7 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@
import { supabase } from '@/integrations/supabase/client';
import { useAuth } from '@/hooks/useAuth';
import { useUserRole } from '@/hooks/useUserRole';
import { useToast } from '@/hooks/use-toast';
import { handleError, handleSuccess } from '@/lib/errorHandler';
// Type-safe role definitions
const VALID_ROLES = ['admin', 'moderator', 'user'] as const;
@@ -66,9 +66,6 @@ export function UserRoleManager() {
isSuperuser,
permissions
} = useUserRole();
const {
toast
} = useToast();
const fetchUserRoles = async () => {
try {
const {
@@ -99,12 +96,10 @@ export function UserRoleManager() {
profiles: profileMap.get(role.user_id)
}));
setUserRoles(userRolesWithProfiles);
} catch (error) {
console.error('Error fetching user roles:', error);
toast({
title: "Error",
description: "Failed to load user roles",
variant: "destructive"
} catch (error: unknown) {
handleError(error, {
action: 'Load User Roles',
userId: user?.id
});
} finally {
setLoading(false);
@@ -144,10 +139,10 @@ export function UserRoleManager() {
// Double-check role validity before database operation
if (!isValidRole(role)) {
toast({
title: "Invalid Role",
description: "The selected role is not valid",
variant: "destructive"
handleError(new Error('Invalid role'), {
action: 'Grant Role',
userId: user?.id,
metadata: { targetUserId: userId, attemptedRole: role }
});
return;
}
@@ -164,20 +159,16 @@ export function UserRoleManager() {
if (error) throw error;
toast({
title: "Role Granted",
description: `User has been granted ${getRoleLabel(role)} role`
});
handleSuccess('Role Granted', `User has been granted ${getRoleLabel(role)} role`);
setNewUserSearch('');
setNewRole('');
setSearchResults([]);
fetchUserRoles();
} catch (error) {
console.error('Error granting role:', error);
toast({
title: "Error",
description: "Failed to grant role",
variant: "destructive"
} catch (error: unknown) {
handleError(error, {
action: 'Grant Role',
userId: user?.id,
metadata: { targetUserId: userId, role }
});
} finally {
setActionLoading(null);
@@ -191,17 +182,13 @@ export function UserRoleManager() {
error
} = await supabase.from('user_roles').delete().eq('id', roleId);
if (error) throw error;
toast({
title: "Role Revoked",
description: "User role has been revoked"
});
handleSuccess('Role Revoked', 'User role has been revoked');
fetchUserRoles();
} catch (error) {
console.error('Error revoking role:', error);
toast({
title: "Error",
description: "Failed to revoke role",
variant: "destructive"
} catch (error: unknown) {
handleError(error, {
action: 'Revoke Role',
userId: user?.id,
metadata: { roleId }
});
} finally {
setActionLoading(null);
@@ -273,10 +260,10 @@ export function UserRoleManager() {
} else if (selectedUser && newRole) {
// This should never happen due to Select component constraints,
// but provides safety in case of UI bugs
toast({
title: "Invalid Role",
description: "Please select a valid role",
variant: "destructive"
handleError(new Error('Invalid role selected'), {
action: 'Grant Role',
userId: user?.id,
metadata: { selectedUser: selectedUser?.user_id, newRole }
});
}
}} disabled={!newRole || !isValidRole(newRole) || !searchResults.find(p => (p.display_name || p.username) === newUserSearch) || actionLoading === 'grant'} className="w-full md:w-auto">