forked from RiseUP/riseup-squad21
listando os users
This commit is contained in:
parent
1b477c10f0
commit
0fee840138
@ -51,7 +51,8 @@ interface User {
|
||||
|
||||
|
||||
interface FlatUser {
|
||||
id: string;
|
||||
id: string;
|
||||
user_id: string;
|
||||
full_name?: string;
|
||||
email: string;
|
||||
phone?: string | null;
|
||||
@ -59,6 +60,7 @@ interface FlatUser {
|
||||
}
|
||||
|
||||
|
||||
|
||||
export default function UsersPage() {
|
||||
const router = useRouter();
|
||||
|
||||
@ -73,69 +75,79 @@ export default function UsersPage() {
|
||||
const [selectedRole, setSelectedRole] = useState<string>("");
|
||||
|
||||
const fetchUsers = useCallback(async () => {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
try {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
try {
|
||||
const data = await usersService.list_roles(); // já retorna o JSON diretamente
|
||||
console.log("Resposta da API list_roles:", data);
|
||||
|
||||
const { data, error } = await usersService.list_roles();
|
||||
if (error) throw error;
|
||||
if (Array.isArray(data)) {
|
||||
const mappedUsers: FlatUser[] = data.map((item: any) => ({
|
||||
id: item.id || (item.user_id ?? ""), // id da linha ou fallback
|
||||
user_id: item.user_id || item.id || "", // garante que user_id exista
|
||||
full_name: item.full_name || "—",
|
||||
email: item.email || "—",
|
||||
phone: item.phone ?? "—",
|
||||
role: item.role || "—",
|
||||
}));
|
||||
|
||||
if (Array.isArray(data)) {
|
||||
setUsers(data as FlatUser[]);
|
||||
} else {
|
||||
console.warn("Formato inesperado recebido:", data);
|
||||
setUsers([]);
|
||||
}
|
||||
} catch (err: any) {
|
||||
console.error("Erro ao buscar usuários:", err);
|
||||
setError("Não foi possível carregar os usuários. Tente novamente.");
|
||||
setUsers(mappedUsers);
|
||||
} else {
|
||||
console.warn("Formato inesperado recebido em list_roles:", data);
|
||||
setUsers([]);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, []);
|
||||
} catch (err: any) {
|
||||
console.error("Erro ao buscar usuários:", err);
|
||||
setError("Não foi possível carregar os usuários. Tente novamente.");
|
||||
setUsers([]);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, []);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
fetchUsers();
|
||||
}, [fetchUsers]);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
const openDetailsDialog = async (flatUser: FlatUser) => {
|
||||
setDetailsDialogOpen(true);
|
||||
setUserDetails(null);
|
||||
|
||||
try {
|
||||
|
||||
const fullUserData: User = await usersService.full_data(flatUser.id);
|
||||
|
||||
|
||||
setUserDetails(fullUserData);
|
||||
|
||||
} catch (err: any) {
|
||||
console.error("Erro ao buscar detalhes do usuário:", err);
|
||||
|
||||
setUserDetails({
|
||||
user: {
|
||||
id: flatUser.id,
|
||||
email: flatUser.email || "",
|
||||
created_at: "Erro ao Carregar",
|
||||
last_sign_in_at: "Erro ao Carregar",
|
||||
},
|
||||
profile: {
|
||||
full_name: "Erro ao Carregar Detalhes",
|
||||
phone: "—",
|
||||
},
|
||||
roles: [],
|
||||
permissions: {},
|
||||
} as any);
|
||||
}
|
||||
};
|
||||
setDetailsDialogOpen(true);
|
||||
setUserDetails(null);
|
||||
|
||||
try {
|
||||
console.log("Buscando detalhes do user_id:", flatUser.user_id);
|
||||
const fullUserData: User = await usersService.full_data(flatUser.user_id);
|
||||
setUserDetails(fullUserData);
|
||||
} catch (err: any) {
|
||||
console.error("Erro ao buscar detalhes do usuário:", err);
|
||||
setUserDetails({
|
||||
user: {
|
||||
id: flatUser.user_id,
|
||||
email: flatUser.email || "",
|
||||
created_at: "Erro ao Carregar",
|
||||
last_sign_in_at: "Erro ao Carregar",
|
||||
},
|
||||
profile: {
|
||||
full_name: flatUser.full_name || "Erro ao Carregar Detalhes",
|
||||
phone: flatUser.phone || "—",
|
||||
},
|
||||
roles: [],
|
||||
permissions: {},
|
||||
} as any);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
const filteredUsers = selectedRole
|
||||
? users.filter((u) => u.role === selectedRole)
|
||||
: users;
|
||||
const filteredUsers = selectedRole && selectedRole !== "all"
|
||||
? users.filter((u) => u.role === selectedRole)
|
||||
: users;
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<ManagerLayout>
|
||||
@ -156,18 +168,19 @@ export default function UsersPage() {
|
||||
<div className="flex items-center space-x-4 bg-white p-4 rounded-lg border border-gray-200">
|
||||
<Filter className="w-5 h-5 text-gray-400" />
|
||||
<Select onValueChange={setSelectedRole} value={selectedRole}>
|
||||
<SelectTrigger className="w-[180px]">
|
||||
<SelectValue placeholder="Filtrar por Papel" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="">Todos</SelectItem>
|
||||
<SelectItem value="admin">Admin</SelectItem>
|
||||
<SelectItem value="gestor">Gestor</SelectItem>
|
||||
<SelectItem value="medico">Médico</SelectItem>
|
||||
<SelectItem value="secretaria">Secretaria</SelectItem>
|
||||
<SelectItem value="user">Usuário</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<SelectTrigger className="w-[180px]">
|
||||
<SelectValue placeholder="Filtrar por Papel" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="all">Todos</SelectItem>
|
||||
<SelectItem value="admin">Admin</SelectItem>
|
||||
<SelectItem value="gestor">Gestor</SelectItem>
|
||||
<SelectItem value="medico">Médico</SelectItem>
|
||||
<SelectItem value="secretaria">Secretaria</SelectItem>
|
||||
<SelectItem value="user">Usuário</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@ -211,7 +224,7 @@ export default function UsersPage() {
|
||||
<td className="px-6 py-4 text-sm text-gray-500 capitalize">{user.role || "—"}</td>
|
||||
<td className="px-6 py-4 text-right">
|
||||
<div className="flex justify-end space-x-1">
|
||||
<Button
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
onClick={() => openDetailsDialog(user)}
|
||||
@ -219,6 +232,7 @@ export default function UsersPage() {
|
||||
>
|
||||
<Eye className="h-4 w-4" />
|
||||
</Button>
|
||||
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
20
package-lock.json
generated
20
package-lock.json
generated
@ -55,9 +55,9 @@
|
||||
"lucide-react": "^0.454.0",
|
||||
"next": "^14.2.33",
|
||||
"next-themes": "^0.4.6",
|
||||
"react": "^18",
|
||||
"react": "^18.3.1",
|
||||
"react-day-picker": "^9.8.0",
|
||||
"react-dom": "^18",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-hook-form": "^7.60.0",
|
||||
"react-resizable-panels": "^2.1.7",
|
||||
"recharts": "2.15.4",
|
||||
@ -70,8 +70,8 @@
|
||||
"devDependencies": {
|
||||
"@tailwindcss/postcss": "^4.1.9",
|
||||
"@types/js-cookie": "^3.0.6",
|
||||
"@types/node": "^22",
|
||||
"@types/react": "^18",
|
||||
"@types/node": "^22.18.10",
|
||||
"@types/react": "^18.3.26",
|
||||
"@types/react-dom": "^18",
|
||||
"postcss": "^8.5",
|
||||
"tailwindcss": "^4.1.9",
|
||||
@ -2496,9 +2496,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "22.18.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.18.6.tgz",
|
||||
"integrity": "sha512-r8uszLPpeIWbNKtvWRt/DbVi5zbqZyj1PTmhRMqBMvDnaz1QpmSKujUtJLrqGZeoM8v72MfYggDceY4K1itzWQ==",
|
||||
"version": "22.18.10",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.18.10.tgz",
|
||||
"integrity": "sha512-anNG/V/Efn/YZY4pRzbACnKxNKoBng2VTFydVu8RRs5hQjikP8CQfaeAV59VFSCzKNp90mXiVXW2QzV56rwMrg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@ -2513,9 +2513,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/react": {
|
||||
"version": "18.3.24",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.24.tgz",
|
||||
"integrity": "sha512-0dLEBsA1kI3OezMBF8nSsb7Nk19ZnsyE1LLhB8r27KbgU5H4pvuqZLdtE+aUkJVoXgTVuA+iLIwmZ0TuK4tx6A==",
|
||||
"version": "18.3.26",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.26.tgz",
|
||||
"integrity": "sha512-RFA/bURkcKzx/X9oumPG9Vp3D3JUgus/d0b67KB0t5S/raciymilkOa66olh78MUI92QLbEJevO7rvqU/kjwKA==",
|
||||
"devOptional": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
|
||||
@ -56,9 +56,9 @@
|
||||
"lucide-react": "^0.454.0",
|
||||
"next": "^14.2.33",
|
||||
"next-themes": "^0.4.6",
|
||||
"react": "^18",
|
||||
"react": "^18.3.1",
|
||||
"react-day-picker": "^9.8.0",
|
||||
"react-dom": "^18",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-hook-form": "^7.60.0",
|
||||
"react-resizable-panels": "^2.1.7",
|
||||
"recharts": "2.15.4",
|
||||
@ -71,8 +71,8 @@
|
||||
"devDependencies": {
|
||||
"@tailwindcss/postcss": "^4.1.9",
|
||||
"@types/js-cookie": "^3.0.6",
|
||||
"@types/node": "^22",
|
||||
"@types/react": "^18",
|
||||
"@types/node": "^22.18.10",
|
||||
"@types/react": "^18.3.26",
|
||||
"@types/react-dom": "^18",
|
||||
"postcss": "^8.5",
|
||||
"tailwindcss": "^4.1.9",
|
||||
|
||||
@ -1,20 +1,7 @@
|
||||
// services/usersApi.mjs (Versão Corrigida)
|
||||
|
||||
import { api } from "./api.mjs";
|
||||
|
||||
export const usersService = {
|
||||
create_user: (data) => api.post(`/functions/v1/create-user`),
|
||||
|
||||
// CORREÇÃO: Voltamos a pedir apenas os campos que sabemos que a view 'user_roles' tem
|
||||
// (id ou user_id, e role), e usamos o endpoint 'full_data' para obter os detalhes de nome/telefone.
|
||||
// SE a sua view 'user_roles' contiver uma coluna chamada 'user_id', tente a próxima linha:
|
||||
// list_roles: () => api.get(`/rest/v1/user_roles?select=user_id,role,profiles(full_name,phone)`),
|
||||
//
|
||||
// PORÉM, VAMOS ASSUMIR QUE A RELAÇÃO ESTÁ REALMENTE QUEBRADA E SIMPLIFICAR A CHAMADA INICIAL:
|
||||
list_roles: () => api.get(`/rest/v1/user_roles?select=id,user_id,email,role`),
|
||||
// Se o email também não estiver em 'user_roles', apenas use 'id,user_id,role'.
|
||||
// O importante é que esta chamada de API NÃO DÊ ERRO 400.
|
||||
|
||||
list_roles: () => api.get(`/rest/v1/user_roles`),
|
||||
full_data: (id) => {
|
||||
const endpoint = `/functions/v1/user-info?user_id=${id}`;
|
||||
return api.get(endpoint);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user