Add user filtering to database queries
Implement user-based filtering in database queries to retrieve data associated with specific users. Determine the users registered today.
This commit is contained in:
parent
b8d0db98bb
commit
6100374e56
8
package-lock.json
generated
8
package-lock.json
generated
@ -41,7 +41,7 @@
|
|||||||
"class-variance-authority": "^0.7.1",
|
"class-variance-authority": "^0.7.1",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"cmdk": "^1.0.0",
|
"cmdk": "^1.0.0",
|
||||||
"date-fns": "^3.6.0",
|
"date-fns": "^4.1.0",
|
||||||
"embla-carousel-react": "^8.3.0",
|
"embla-carousel-react": "^8.3.0",
|
||||||
"input-otp": "^1.2.4",
|
"input-otp": "^1.2.4",
|
||||||
"lucide-react": "^0.462.0",
|
"lucide-react": "^0.462.0",
|
||||||
@ -4196,9 +4196,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/date-fns": {
|
"node_modules/date-fns": {
|
||||||
"version": "3.6.0",
|
"version": "4.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz",
|
||||||
"integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==",
|
"integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"funding": {
|
"funding": {
|
||||||
"type": "github",
|
"type": "github",
|
||||||
|
|||||||
@ -44,7 +44,7 @@
|
|||||||
"class-variance-authority": "^0.7.1",
|
"class-variance-authority": "^0.7.1",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"cmdk": "^1.0.0",
|
"cmdk": "^1.0.0",
|
||||||
"date-fns": "^3.6.0",
|
"date-fns": "^4.1.0",
|
||||||
"embla-carousel-react": "^8.3.0",
|
"embla-carousel-react": "^8.3.0",
|
||||||
"input-otp": "^1.2.4",
|
"input-otp": "^1.2.4",
|
||||||
"lucide-react": "^0.462.0",
|
"lucide-react": "^0.462.0",
|
||||||
|
|||||||
45
src/components/usuarios/UsersDialog.tsx
Normal file
45
src/components/usuarios/UsersDialog.tsx
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import UsersList from "./UsersList";
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogDescription,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle,
|
||||||
|
DialogTrigger,
|
||||||
|
} from "@/components/ui/dialog";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { UserRoundSearch } from "lucide-react";
|
||||||
|
|
||||||
|
interface UsersDialogProps {
|
||||||
|
trigger?: React.ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function UsersDialog({ trigger }: UsersDialogProps) {
|
||||||
|
return (
|
||||||
|
<Dialog>
|
||||||
|
<DialogTrigger asChild>
|
||||||
|
{trigger || (
|
||||||
|
<Button variant="outline" size="sm" className="gap-2">
|
||||||
|
<UserRoundSearch className="h-4 w-4" />
|
||||||
|
<span>Usuários</span>
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</DialogTrigger>
|
||||||
|
<DialogContent className="sm:max-w-[700px] max-h-[80vh] overflow-y-auto">
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>Gerenciamento de Usuários</DialogTitle>
|
||||||
|
<DialogDescription>
|
||||||
|
Visualize e gerencie os usuários cadastrados na plataforma
|
||||||
|
</DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
<div className="py-4">
|
||||||
|
<UsersList />
|
||||||
|
</div>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default UsersDialog;
|
||||||
143
src/components/usuarios/UsersList.tsx
Normal file
143
src/components/usuarios/UsersList.tsx
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
|
||||||
|
import React, { useState, useEffect } from 'react';
|
||||||
|
import { format } from 'date-fns';
|
||||||
|
import { ptBR } from 'date-fns/locale';
|
||||||
|
import { UserInfo, getUsersRegisteredToday, getAllUsers } from '@/services/userService';
|
||||||
|
import {
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
CardDescription,
|
||||||
|
CardFooter,
|
||||||
|
CardHeader,
|
||||||
|
CardTitle,
|
||||||
|
} from "@/components/ui/card";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||||
|
import { useToast } from "@/hooks/use-toast";
|
||||||
|
|
||||||
|
const UsersList: React.FC = () => {
|
||||||
|
const [usersToday, setUsersToday] = useState<UserInfo[]>([]);
|
||||||
|
const [allUsers, setAllUsers] = useState<UserInfo[]>([]);
|
||||||
|
const [loading, setLoading] = useState<boolean>(false);
|
||||||
|
const [activeTab, setActiveTab] = useState<string>("today");
|
||||||
|
const { toast } = useToast();
|
||||||
|
|
||||||
|
const loadUsers = async (tab: string = activeTab) => {
|
||||||
|
setLoading(true);
|
||||||
|
try {
|
||||||
|
if (tab === "today") {
|
||||||
|
const users = await getUsersRegisteredToday();
|
||||||
|
setUsersToday(users);
|
||||||
|
} else {
|
||||||
|
const users = await getAllUsers();
|
||||||
|
setAllUsers(users);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Erro ao carregar usuários:", error);
|
||||||
|
toast({
|
||||||
|
title: "Erro",
|
||||||
|
description: "Falha ao carregar dados de usuários.",
|
||||||
|
variant: "destructive",
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
loadUsers();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleTabChange = (value: string) => {
|
||||||
|
setActiveTab(value);
|
||||||
|
loadUsers(value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const formatDate = (dateString: string) => {
|
||||||
|
try {
|
||||||
|
return format(new Date(dateString), "dd/MM/yyyy HH:mm", { locale: ptBR });
|
||||||
|
} catch (error) {
|
||||||
|
return "Data inválida";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const displayUsers = activeTab === "today" ? usersToday : allUsers;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card className="w-full">
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle>Usuários Cadastrados</CardTitle>
|
||||||
|
<CardDescription>
|
||||||
|
{activeTab === "today"
|
||||||
|
? `${usersToday.length} usuários cadastrados hoje`
|
||||||
|
: `${allUsers.length} usuários cadastrados no total`}
|
||||||
|
</CardDescription>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<Tabs defaultValue="today" onValueChange={handleTabChange}>
|
||||||
|
<TabsList className="mb-4">
|
||||||
|
<TabsTrigger value="today">Cadastrados Hoje</TabsTrigger>
|
||||||
|
<TabsTrigger value="all">Todos os Usuários</TabsTrigger>
|
||||||
|
</TabsList>
|
||||||
|
|
||||||
|
<TabsContent value="today" className="space-y-4">
|
||||||
|
{loading ? (
|
||||||
|
<div className="text-center py-4">Carregando...</div>
|
||||||
|
) : usersToday.length > 0 ? (
|
||||||
|
<div className="space-y-2">
|
||||||
|
{usersToday.map((user) => (
|
||||||
|
<div key={user.id} className="border p-4 rounded-md">
|
||||||
|
<div className="font-semibold">{user.nome}</div>
|
||||||
|
<div className="text-sm text-muted-foreground">Email: {user.email}</div>
|
||||||
|
{user.empresa && (
|
||||||
|
<div className="text-sm text-muted-foreground">Empresa: {user.empresa}</div>
|
||||||
|
)}
|
||||||
|
<div className="text-xs text-muted-foreground mt-1">
|
||||||
|
Cadastrado em: {formatDate(user.created_at)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="text-center py-4">Nenhum usuário cadastrado hoje.</div>
|
||||||
|
)}
|
||||||
|
</TabsContent>
|
||||||
|
|
||||||
|
<TabsContent value="all" className="space-y-4">
|
||||||
|
{loading ? (
|
||||||
|
<div className="text-center py-4">Carregando...</div>
|
||||||
|
) : allUsers.length > 0 ? (
|
||||||
|
<div className="space-y-2">
|
||||||
|
{allUsers.map((user) => (
|
||||||
|
<div key={user.id} className="border p-4 rounded-md">
|
||||||
|
<div className="font-semibold">{user.nome}</div>
|
||||||
|
<div className="text-sm text-muted-foreground">Email: {user.email}</div>
|
||||||
|
{user.empresa && (
|
||||||
|
<div className="text-sm text-muted-foreground">Empresa: {user.empresa}</div>
|
||||||
|
)}
|
||||||
|
<div className="text-xs text-muted-foreground mt-1">
|
||||||
|
Cadastrado em: {formatDate(user.created_at)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="text-center py-4">Nenhum usuário cadastrado.</div>
|
||||||
|
)}
|
||||||
|
</TabsContent>
|
||||||
|
</Tabs>
|
||||||
|
</CardContent>
|
||||||
|
<CardFooter className="flex justify-end">
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
onClick={() => loadUsers(activeTab)}
|
||||||
|
disabled={loading}
|
||||||
|
>
|
||||||
|
{loading ? "Carregando..." : "Atualizar"}
|
||||||
|
</Button>
|
||||||
|
</CardFooter>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default UsersList;
|
||||||
@ -154,6 +154,7 @@ export type Database = {
|
|||||||
detalhes: string | null
|
detalhes: string | null
|
||||||
estabelecimento: string | null
|
estabelecimento: string | null
|
||||||
id: number
|
id: number
|
||||||
|
login: string | null
|
||||||
quando: string | null
|
quando: string | null
|
||||||
tipo: string | null
|
tipo: string | null
|
||||||
user: string | null
|
user: string | null
|
||||||
@ -165,6 +166,7 @@ export type Database = {
|
|||||||
detalhes?: string | null
|
detalhes?: string | null
|
||||||
estabelecimento?: string | null
|
estabelecimento?: string | null
|
||||||
id?: number
|
id?: number
|
||||||
|
login?: string | null
|
||||||
quando?: string | null
|
quando?: string | null
|
||||||
tipo?: string | null
|
tipo?: string | null
|
||||||
user?: string | null
|
user?: string | null
|
||||||
@ -176,6 +178,7 @@ export type Database = {
|
|||||||
detalhes?: string | null
|
detalhes?: string | null
|
||||||
estabelecimento?: string | null
|
estabelecimento?: string | null
|
||||||
id?: number
|
id?: number
|
||||||
|
login?: string | null
|
||||||
quando?: string | null
|
quando?: string | null
|
||||||
tipo?: string | null
|
tipo?: string | null
|
||||||
user?: string | null
|
user?: string | null
|
||||||
|
|||||||
@ -1,20 +1,22 @@
|
|||||||
|
|
||||||
import { useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import Layout from '@/components/layout/Layout';
|
import Layout from '@/components/layout/Layout';
|
||||||
import { WhatsAppInstance } from '@/types/whatsAppTypes';
|
import {
|
||||||
import CreateInstanceForm from '@/components/whatsapp/CreateInstanceForm';
|
CreateInstanceForm,
|
||||||
import InstanceList from '@/components/whatsapp/InstanceList';
|
InstanceList,
|
||||||
import InstanceStats from '@/components/whatsapp/InstanceStats';
|
InstanceStats,
|
||||||
import QrCodeDialog from '@/components/whatsapp/QrCodeDialog';
|
QrCodeDialog
|
||||||
|
} from '@/components/whatsapp';
|
||||||
|
import { Button } from '@/components/ui/button';
|
||||||
|
import UsersDialog from '@/components/usuarios/UsersDialog';
|
||||||
import { useWhatsAppInstances } from '@/hooks/useWhatsAppInstances';
|
import { useWhatsAppInstances } from '@/hooks/useWhatsAppInstances';
|
||||||
import { useWhatsAppActions } from '@/hooks/useWhatsAppActions';
|
import { useWhatsAppActions } from '@/hooks/useWhatsAppActions';
|
||||||
import { useToast } from '@/hooks/use-toast';
|
|
||||||
|
|
||||||
const WhatsApp = () => {
|
const WhatsApp = () => {
|
||||||
const { toast } = useToast();
|
|
||||||
const {
|
const {
|
||||||
instances,
|
instances,
|
||||||
isRefreshing,
|
isRefreshing,
|
||||||
|
currentUserId,
|
||||||
addInstance,
|
addInstance,
|
||||||
removeInstance,
|
removeInstance,
|
||||||
updateInstance,
|
updateInstance,
|
||||||
@ -33,119 +35,72 @@ const WhatsApp = () => {
|
|||||||
handleViewQrCode
|
handleViewQrCode
|
||||||
} = useWhatsAppActions(updateInstance, removeInstance, checkAllInstancesStatus);
|
} = useWhatsAppActions(updateInstance, removeInstance, checkAllInstancesStatus);
|
||||||
|
|
||||||
// Set up periodic status checks
|
// Poll for status updates every 30 seconds
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log("Setting up periodic status checks, current instances:", instances.length);
|
let interval: ReturnType<typeof setInterval> | null = null;
|
||||||
|
|
||||||
// Check status initially
|
const startPolling = () => {
|
||||||
if (instances.length > 0) {
|
interval = setInterval(() => {
|
||||||
|
console.log("Polling for WhatsApp instance status updates");
|
||||||
checkAllInstancesStatus();
|
checkAllInstancesStatus();
|
||||||
}
|
}, 30000); // Check every 30 seconds
|
||||||
|
};
|
||||||
|
|
||||||
// Set up interval for periodic checks (every 30 seconds)
|
// Start polling
|
||||||
const interval = setInterval(() => {
|
startPolling();
|
||||||
if (instances.length > 0) {
|
|
||||||
console.log("Running periodic status check");
|
|
||||||
checkAllInstancesStatus();
|
|
||||||
}
|
|
||||||
}, 30000); // 30 seconds
|
|
||||||
|
|
||||||
// Clean up interval when component unmounts
|
// Cleanup on unmount
|
||||||
return () => {
|
return () => {
|
||||||
if (interval) {
|
if (interval) {
|
||||||
clearInterval(interval);
|
clearInterval(interval);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}, [instances.length, checkAllInstancesStatus]);
|
}, [checkAllInstancesStatus]);
|
||||||
|
|
||||||
// Run refresh instances on initial load to get server instances
|
|
||||||
useEffect(() => {
|
|
||||||
const initialLoad = async () => {
|
|
||||||
if (instances.length === 0) {
|
|
||||||
try {
|
|
||||||
await refreshInstances();
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error on initial instance refresh:", error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
initialLoad();
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
// Handler for when a new instance is created
|
|
||||||
const handleInstanceCreated = async (newInstance: WhatsAppInstance) => {
|
|
||||||
console.log('New instance to be added:', newInstance);
|
|
||||||
addInstance(newInstance);
|
|
||||||
|
|
||||||
// If there's a QR code in the response, show it
|
|
||||||
if (newInstance.qrcode) {
|
|
||||||
handleViewQrCode(newInstance);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Trigger a status check for all instances
|
|
||||||
try {
|
|
||||||
await checkAllInstancesStatus();
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error checking status after instance creation:", error);
|
|
||||||
toast({
|
|
||||||
title: "Aviso",
|
|
||||||
description: "Instância criada, mas não foi possível verificar o status. Tente atualizar a lista manualmente.",
|
|
||||||
variant: "default",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Handler for when an instance is deleted
|
|
||||||
const handleDeleteInstanceWrapper = (instanceId: string) => {
|
|
||||||
console.log(`Instance deletion requested for ID: ${instanceId}`);
|
|
||||||
const instanceToDelete = instances.find(i => i.instanceId === instanceId);
|
|
||||||
if (instanceToDelete) {
|
|
||||||
handleDeleteInstance(instanceId, instanceToDelete.instanceName);
|
|
||||||
} else {
|
|
||||||
console.error(`Instance with ID ${instanceId} not found for deletion`);
|
|
||||||
toast({
|
|
||||||
title: "Erro",
|
|
||||||
description: "Instância não encontrada para exclusão",
|
|
||||||
variant: "destructive",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
console.log('Current instances in WhatsApp component:', instances);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Layout>
|
<Layout>
|
||||||
<div className="space-y-6">
|
<div className="container mx-auto p-4">
|
||||||
<div className="flex justify-between items-center">
|
<div className="flex flex-col md:flex-row justify-between items-center mb-6">
|
||||||
<h1 className="text-2xl font-bold tracking-tight">Conectar WhatsApp</h1>
|
<h1 className="text-2xl font-bold mb-4 md:mb-0">WhatsApp Instances</h1>
|
||||||
|
<div className="flex gap-2 items-center">
|
||||||
|
<UsersDialog />
|
||||||
|
<Button
|
||||||
|
onClick={refreshInstances}
|
||||||
|
disabled={isRefreshing}
|
||||||
|
variant="outline"
|
||||||
|
>
|
||||||
|
{isRefreshing ? 'Atualizando...' : 'Atualizar Instâncias'}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Form to create a new instance */}
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||||||
<CreateInstanceForm onInstanceCreated={handleInstanceCreated} />
|
<div className="md:col-span-2">
|
||||||
|
<CreateInstanceForm userId={currentUserId} onInstanceCreated={addInstance} />
|
||||||
{/* Stats component */}
|
<div className="mt-8">
|
||||||
<InstanceStats instances={instances} />
|
|
||||||
|
|
||||||
{/* List of created instances */}
|
|
||||||
<InstanceList
|
<InstanceList
|
||||||
instances={instances}
|
instances={instances}
|
||||||
onViewQrCode={handleViewQrCode}
|
onRestartInstance={handleRestartInstance}
|
||||||
onDelete={handleDeleteInstanceWrapper}
|
onLogoutInstance={handleLogoutInstance}
|
||||||
onRestart={handleRestartInstance}
|
|
||||||
onLogout={handleLogoutInstance}
|
|
||||||
onSetPresence={handleSetPresence}
|
onSetPresence={handleSetPresence}
|
||||||
onRefreshInstances={refreshInstances}
|
onDeleteInstance={handleDeleteInstance}
|
||||||
isRefreshing={isRefreshing}
|
onViewQrCode={handleViewQrCode}
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<InstanceStats instances={instances} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* QR Code Dialog */}
|
{activeInstance && (
|
||||||
<QrCodeDialog
|
<QrCodeDialog
|
||||||
open={qrDialogOpen}
|
open={qrDialogOpen}
|
||||||
onOpenChange={setQrDialogOpen}
|
setOpen={setQrDialogOpen}
|
||||||
activeInstance={activeInstance}
|
instanceName={activeInstance.instanceName}
|
||||||
onStatusCheck={checkAllInstancesStatus}
|
phoneNumber={activeInstance.phoneNumber}
|
||||||
/>
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</Layout>
|
</Layout>
|
||||||
);
|
);
|
||||||
|
|||||||
62
src/services/userService.ts
Normal file
62
src/services/userService.ts
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
|
||||||
|
import { supabase } from "@/integrations/supabase/client";
|
||||||
|
import { format } from "date-fns";
|
||||||
|
|
||||||
|
export interface UserInfo {
|
||||||
|
id: string;
|
||||||
|
nome: string;
|
||||||
|
email: string;
|
||||||
|
empresa: string | null;
|
||||||
|
created_at: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getUsersRegisteredToday = async (): Promise<UserInfo[]> => {
|
||||||
|
try {
|
||||||
|
console.log("Buscando usuários cadastrados hoje...");
|
||||||
|
// Obtém a data atual no formato YYYY-MM-DD
|
||||||
|
const today = format(new Date(), 'yyyy-MM-dd');
|
||||||
|
|
||||||
|
// Busca usuários cadastrados hoje
|
||||||
|
const { data, error } = await supabase
|
||||||
|
.from("usuarios")
|
||||||
|
.select("*")
|
||||||
|
.gte('created_at', `${today}T00:00:00`) // Data início (hoje 00:00:00)
|
||||||
|
.lte('created_at', `${today}T23:59:59`) // Data fim (hoje 23:59:59)
|
||||||
|
.order('created_at', { ascending: false });
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
console.error("Erro ao buscar usuários:", error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`Encontrados ${data?.length || 0} usuários cadastrados hoje:`, data);
|
||||||
|
|
||||||
|
return data as UserInfo[];
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Erro ao buscar usuários cadastrados hoje:", error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getAllUsers = async (): Promise<UserInfo[]> => {
|
||||||
|
try {
|
||||||
|
console.log("Buscando todos os usuários...");
|
||||||
|
|
||||||
|
const { data, error } = await supabase
|
||||||
|
.from("usuarios")
|
||||||
|
.select("*")
|
||||||
|
.order('created_at', { ascending: false });
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
console.error("Erro ao buscar usuários:", error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`Encontrados ${data?.length || 0} usuários no total`);
|
||||||
|
|
||||||
|
return data as UserInfo[];
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Erro ao buscar todos os usuários:", error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
};
|
||||||
Loading…
Reference in New Issue
Block a user