Merge pull request #26 from m1guelmcf/visual

pequenos ajustes
This commit is contained in:
DaniloSts 2025-11-26 19:37:41 -03:00 committed by GitHub
commit 883411b8a3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 155 additions and 290 deletions

View File

@ -144,10 +144,6 @@ export default function EditarLaudoPage() {
<CardContent> <CardContent>
<form onSubmit={handleSubmit} className="space-y-6"> <form onSubmit={handleSubmit} className="space-y-6">
<div className="grid grid-cols-1 md:grid-cols-2 gap-6"> <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<div className="space-y-2">
<Label htmlFor="order_number"> do Pedido</Label>
<Input id="order_number" value={formData.order_number || ''} onChange={handleInputChange} />
</div>
<div className="space-y-2"> <div className="space-y-2">
<Label htmlFor="exam">Exame</Label> <Label htmlFor="exam">Exame</Label>
<Input id="exam" value={formData.exam || ''} onChange={handleInputChange} /> <Input id="exam" value={formData.exam || ''} onChange={handleInputChange} />

View File

@ -1,5 +1,4 @@
"use client";
"use client";
import { useParams, useRouter } from "next/navigation"; import { useParams, useRouter } from "next/navigation";
import { useState } from "react"; import { useState } from "react";
@ -106,10 +105,6 @@ export default function NovoLaudoPage() {
<CardContent> <CardContent>
<form onSubmit={handleSubmit} className="space-y-6"> <form onSubmit={handleSubmit} className="space-y-6">
<div className="grid grid-cols-1 md:grid-cols-2 gap-6"> <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<div className="space-y-2">
<Label htmlFor="order_number"> do Pedido</Label>
<Input id="order_number" value={formData.order_number} onChange={handleInputChange} />
</div>
<div className="space-y-2"> <div className="space-y-2">
<Label htmlFor="exam">Exame</Label> <Label htmlFor="exam">Exame</Label>
<Input id="exam" value={formData.exam} onChange={handleInputChange} /> <Input id="exam" value={formData.exam} onChange={handleInputChange} />

View File

@ -8,7 +8,7 @@ import {
DropdownMenuItem, DropdownMenuItem,
DropdownMenuTrigger, DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"; } from "@/components/ui/dropdown-menu";
import { Eye, Edit, Calendar, Trash2, Loader2 } from "lucide-react"; import { Eye, Edit, Calendar, Trash2, Loader2, MoreVertical } from "lucide-react";
import { api } from "@/services/api.mjs"; import { api } from "@/services/api.mjs";
import { PatientDetailsModal } from "@/components/ui/patient-details-modal"; import { PatientDetailsModal } from "@/components/ui/patient-details-modal";
import { import {
@ -283,9 +283,10 @@ export default function PacientesPage() {
<td className="p-3 sm:p-4"> <td className="p-3 sm:p-4">
<DropdownMenu> <DropdownMenu>
<DropdownMenuTrigger asChild> <DropdownMenuTrigger asChild>
<button className="text-primary hover:underline text-sm sm:text-base"> <Button variant="ghost" className="h-8 w-8 p-0">
Ações <span className="sr-only">Abrir menu</span>
</button> <MoreVertical className="h-4 w-4" />
</Button>
</DropdownMenuTrigger> </DropdownMenuTrigger>
<DropdownMenuContent align="end"> <DropdownMenuContent align="end">
<DropdownMenuItem <DropdownMenuItem
@ -295,19 +296,11 @@ export default function PacientesPage() {
Ver detalhes Ver detalhes
</DropdownMenuItem> </DropdownMenuItem>
<DropdownMenuItem asChild> <DropdownMenuItem asChild>
<Link href={`/doctor/pacientes/${p.id}/laudos`}> <Link href={`/doctor/medicos/${p.id}/laudos`}>
<Edit className="w-4 h-4 mr-2" /> <Edit className="w-4 h-4 mr-2" />
Laudos Laudos
</Link> </Link>
</DropdownMenuItem> </DropdownMenuItem>
<DropdownMenuItem
onClick={() =>
alert(`Agenda para paciente ID: ${p.id}`)
}
>
<Calendar className="w-4 h-4 mr-2" />
Ver agenda
</DropdownMenuItem>
<DropdownMenuItem <DropdownMenuItem
onClick={() => { onClick={() => {
const newPacientes = pacientes.filter( const newPacientes = pacientes.filter(

View File

@ -6,7 +6,7 @@ import { useRouter } from "next/navigation";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Edit, Trash2, Eye, Calendar, Loader2 } from "lucide-react"; import { Edit, Trash2, Eye, Calendar, Loader2, MoreVertical } from "lucide-react";
import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle } from "@/components/ui/alert-dialog"; import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle } from "@/components/ui/alert-dialog";
// Imports dos Serviços // Imports dos Serviços
@ -326,7 +326,9 @@ export default function DoctorsPage() {
<td className="px-4 py-3 text-right"> <td className="px-4 py-3 text-right">
<DropdownMenu> <DropdownMenu>
<DropdownMenuTrigger asChild> <DropdownMenuTrigger asChild>
<div className="text-blue-600 cursor-pointer inline-block hover:underline">Ações</div> <div className="text-black-600 cursor-pointer inline-block">
<MoreVertical className="h-4 w-4" />
</div>
</DropdownMenuTrigger> </DropdownMenuTrigger>
<DropdownMenuContent align="end"> <DropdownMenuContent align="end">
<DropdownMenuItem onClick={() => openDetailsDialog(doctor)}> <DropdownMenuItem onClick={() => openDetailsDialog(doctor)}>

View File

@ -3,30 +3,10 @@
import { useState, useEffect, useCallback } from "react"; import { useState, useEffect, useCallback } from "react";
import Link from "next/link"; import Link from "next/link";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
DropdownMenu, import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
DropdownMenuContent, import { Plus, Edit, Trash2, Eye, Calendar, Filter, Loader2, MoreVertical } from "lucide-react";
DropdownMenuItem, import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle } from "@/components/ui/alert-dialog";
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { Edit, Trash2, Eye, Calendar, Filter, Loader2 } from "lucide-react";
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
} from "@/components/ui/alert-dialog";
import { patientsService } from "@/services/patientsApi.mjs"; import { patientsService } from "@/services/patientsApi.mjs";
import Sidebar from "@/components/Sidebar"; import Sidebar from "@/components/Sidebar";
@ -291,107 +271,39 @@ export default function PacientesPage() {
<td className="p-4"> <td className="p-4">
<DropdownMenu> <DropdownMenu>
<DropdownMenuTrigger asChild> <DropdownMenuTrigger asChild>
<div className="text-blue-600 cursor-pointer">Ações</div> <div className="text-black-600 cursor-pointer">
<MoreVertical className="h-4 w-4" />
</div>
</DropdownMenuTrigger> </DropdownMenuTrigger>
<DropdownMenuContent align="end"> <DropdownMenuContent align="end">
<DropdownMenuItem onClick={() => openDetailsDialog(String(patient.id))}> <DropdownMenuItem onClick={() => openDetailsDialog(String(patient.id))}>
<Eye className="w-4 h-4 mr-2" /> <Eye className="w-4 h-4 mr-2" />
Ver detalhes Ver detalhes
</DropdownMenuItem> </DropdownMenuItem>
<DropdownMenuItem asChild>
<Link href={`/secretary/pacientes/${patient.id}/editar`} className="flex items-center w-full">
<Edit className="w-4 h-4 mr-2" />
Editar
</Link>
</DropdownMenuItem>
<DropdownMenuItem asChild> <DropdownMenuItem>
<Link <Calendar className="w-4 h-4 mr-2" />
href={`/secretary/pacientes/${patient.id}/editar`} Marcar consulta
className="flex items-center w-full" </DropdownMenuItem>
> <DropdownMenuItem className="text-red-600" onClick={() => openDeleteDialog(String(patient.id))}>
<Edit className="w-4 h-4 mr-2" /> <Trash2 className="w-4 h-4 mr-2" />
Editar Excluir
</Link> </DropdownMenuItem>
</DropdownMenuItem> </DropdownMenuContent>
</DropdownMenu>
<DropdownMenuItem> </td>
<Calendar className="w-4 h-4 mr-2" /> </tr>
Marcar consulta )))}
</DropdownMenuItem> </tbody>
<DropdownMenuItem </table>
className="text-red-600" )}
onClick={() => </div>
openDeleteDialog(String(patient.id))
}
>
<Trash2 className="w-4 h-4 mr-2" />
Excluir
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</td>
</tr>
))
)}
</tbody>
</table>
)}
</div>
</div>
{/* --- SEÇÃO DE CARDS (VISÍVEL APENAS EM TELAS MENORES QUE MD) --- */}
{/* Garantir que os cards apareçam em telas menores e se escondam em MD+ */}
<div className="bg-white rounded-lg border border-gray-200 shadow-md p-4 block md:hidden">
{error ? (
<div className="p-6 text-red-600">{`Erro ao carregar pacientes: ${error}`}</div>
) : loading ? (
<div className="p-6 text-center text-gray-500 flex items-center justify-center">
<Loader2 className="w-6 h-6 mr-2 animate-spin text-green-600" /> Carregando pacientes...
</div>
) : filteredPatients.length === 0 ? (
<div className="p-8 text-center text-gray-500">
{allPatients.length === 0 ? "Nenhum paciente cadastrado" : "Nenhum paciente encontrado com os filtros aplicados"}
</div>
) : (
<div className="space-y-4">
{currentPatients.map((patient) => (
<div key={patient.id} className="bg-gray-50 rounded-lg p-4 flex flex-col sm:flex-row justify-between items-start sm:items-center border border-gray-200">
<div className="flex-grow mb-2 sm:mb-0">
<div className="font-semibold text-lg text-gray-900 flex items-center">
{patient.nome}
{patient.vip && (
<span className="ml-2 px-2 py-0.5 text-xs font-semibold text-purple-600 bg-purple-100 rounded-full">VIP</span>
)}
</div>
<div className="text-sm text-gray-600">Telefone: {patient.telefone}</div>
<div className="text-sm text-gray-600">Convênio: {patient.convenio}</div>
</div>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<div className="w-full"><Button variant="outline" className="w-full">Ações</Button></div>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuItem onClick={() => openDetailsDialog(String(patient.id))}>
<Eye className="w-4 h-4 mr-2" />
Ver detalhes
</DropdownMenuItem>
<DropdownMenuItem asChild>
<Link href={`/secretary/pacientes/${patient.id}/editar`} className="flex items-center w-full">
<Edit className="w-4 h-4 mr-2" />
Editar
</Link>
</DropdownMenuItem>
<DropdownMenuItem>
<Calendar className="w-4 h-4 mr-2" />
Marcar consulta
</DropdownMenuItem>
<DropdownMenuItem className="text-red-600" onClick={() => openDeleteDialog(String(patient.id))}>
<Trash2 className="w-4 h-4 mr-2" />
Excluir
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</div>
))}
</div>
)}
</div> </div>
{/* Paginação */} {/* Paginação */}

View File

@ -283,33 +283,24 @@ export default function SecretaryAppointments() {
</div> </div>
</div> </div>
<div className="flex gap-2 mt-4 pt-4 border-t"> <div className="flex gap-2 mt-4 pt-4 border-t">
<Button <Button variant="outline" size="sm" onClick={() => handleEdit(appointment)}>
variant="outline" <Pencil className="mr-2 h-4 w-4" />
size="sm" Editar
onClick={() => handleEdit(appointment)} </Button>
> <Button variant="outline" size="sm" className="text-red-600 hover:text-red-700 hover:bg-red-50 bg-transparent" onClick={() => handleDelete(appointment)}>
<Pencil className="mr-2 h-4 w-4" /> <Trash2 className="mr-2 h-4 w-4" />
Editar Cancelar
</Button> </Button>
<Button </div>
variant="outline" </CardContent>
size="sm" </Card>
className="text-red-600 hover:text-red-700 hover:bg-red-50 bg-transparent" ))
onClick={() => handleDelete(appointment)} ) : (
> <p>Nenhuma consulta encontrada.</p>
<Trash2 className="mr-2 h-4 w-4" /> )}
Deletar </div>
</Button> </div>
</div>
</CardContent>
</Card>
))
) : (
<p>Nenhuma consulta encontrada.</p>
)}
</div>
</div>
{/* MODAL DE EDIÇÃO */} {/* MODAL DE EDIÇÃO */}
<Dialog open={editModal} onOpenChange={setEditModal}> <Dialog open={editModal} onOpenChange={setEditModal}>

View File

@ -4,38 +4,11 @@
import { useState, useEffect, useCallback } from "react"; import { useState, useEffect, useCallback } from "react";
import Link from "next/link"; import Link from "next/link";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
DropdownMenu, import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
DropdownMenuContent, import { Plus, Edit, Trash2, Eye, Calendar, Filter, Loader2, MoreVertical } from "lucide-react";
DropdownMenuItem, import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle } from "@/components/ui/alert-dialog";
DropdownMenuTrigger, import SecretaryLayout from "@/components/secretary-layout";
} from "@/components/ui/dropdown-menu";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import {
Plus,
Edit,
Trash2,
Eye,
Calendar,
Filter,
Loader2,
} from "lucide-react";
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
} from "@/components/ui/alert-dialog";
import { patientsService } from "@/services/patientsApi.mjs"; import { patientsService } from "@/services/patientsApi.mjs";
import Sidebar from "@/components/Sidebar"; import Sidebar from "@/components/Sidebar";
@ -43,58 +16,59 @@ import Sidebar from "@/components/Sidebar";
const PAGE_SIZE = 5; const PAGE_SIZE = 5;
export default function PacientesPage() { export default function PacientesPage() {
// --- ESTADOS DE DADOS E GERAL --- // --- ESTADOS DE DADOS E GERAL ---
const [searchTerm, setSearchTerm] = useState(""); const [searchTerm, setSearchTerm] = useState("");
const [convenioFilter, setConvenioFilter] = useState("all"); const [convenioFilter, setConvenioFilter] = useState("all");
const [vipFilter, setVipFilter] = useState("all"); const [vipFilter, setVipFilter] = useState("all");
// Lista completa, carregada da API uma única vez // Lista completa, carregada da API uma única vez
const [allPatients, setAllPatients] = useState<any[]>([]); const [allPatients, setAllPatients] = useState<any[]>([]);
// Lista após a aplicação dos filtros (base para a paginação) // Lista após a aplicação dos filtros (base para a paginação)
const [filteredPatients, setFilteredPatients] = useState<any[]>([]); const [filteredPatients, setFilteredPatients] = useState<any[]>([]);
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null); const [error, setError] = useState<string | null>(null);
// --- ESTADOS DE PAGINAÇÃO --- // --- ESTADOS DE PAGINAÇÃO ---
const [page, setPage] = useState(1); const [page, setPage] = useState(1);
// CÁLCULO DA PAGINAÇÃO // CÁLCULO DA PAGINAÇÃO
const totalPages = Math.ceil(filteredPatients.length / PAGE_SIZE); const totalPages = Math.ceil(filteredPatients.length / PAGE_SIZE);
const startIndex = (page - 1) * PAGE_SIZE; const startIndex = (page - 1) * PAGE_SIZE;
const endIndex = startIndex + PAGE_SIZE; const endIndex = startIndex + PAGE_SIZE;
// Pacientes a serem exibidos na tabela (aplicando a paginação) // Pacientes a serem exibidos na tabela (aplicando a paginação)
const currentPatients = filteredPatients.slice(startIndex, endIndex); const currentPatients = filteredPatients.slice(startIndex, endIndex);
// --- ESTADOS DE DIALOGS --- // --- ESTADOS DE DIALOGS ---
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false); const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
const [patientToDelete, setPatientToDelete] = useState<string | null>(null); const [patientToDelete, setPatientToDelete] = useState<string | null>(null);
const [detailsDialogOpen, setDetailsDialogOpen] = useState(false); const [detailsDialogOpen, setDetailsDialogOpen] = useState(false);
const [patientDetails, setPatientDetails] = useState<any | null>(null); const [patientDetails, setPatientDetails] = useState<any | null>(null);
// --- FUNÇÕES DE LÓGICA --- // --- FUNÇÕES DE LÓGICA ---
// 1. Função para carregar TODOS os pacientes da API // 1. Função para carregar TODOS os pacientes da API
const fetchAllPacientes = useCallback(async () => { const fetchAllPacientes = useCallback(
setLoading(true); async () => {
setError(null); setLoading(true);
try { setError(null);
// Como o backend retorna um array, chamamos sem paginação try {
const res = await patientsService.list(); // Como o backend retorna um array, chamamos sem paginação
const res = await patientsService.list();
const mapped = res.map((p: any) => ({ const mapped = res.map((p: any) => ({
id: String(p.id ?? ""), id: String(p.id ?? ""),
nome: p.full_name ?? "—", nome: p.full_name ?? "—",
telefone: p.phone_mobile ?? p.phone1 ?? "—", telefone: p.phone_mobile ?? p.phone1 ?? "—",
cidade: p.city ?? "—", cidade: p.city ?? "—",
estado: p.state ?? "—", estado: p.state ?? "—",
// Formate as datas se necessário, aqui usamos como string // Formate as datas se necessário, aqui usamos como string
ultimoAtendimento: p.last_visit_at?.split("T")[0] ?? "—", ultimoAtendimento: p.last_visit_at?.split('T')[0] ?? "—",
proximoAtendimento: p.next_appointment_at?.split("T")[0] ?? "—", proximoAtendimento: p.next_appointment_at?.split('T')[0] ?? "—",
vip: Boolean(p.vip ?? false), vip: Boolean(p.vip ?? false),
convenio: p.convenio ?? "Particular", // Define um valor padrão convenio: p.convenio ?? "Particular", // Define um valor padrão
status: p.status ?? undefined, status: p.status ?? undefined,
})); }));
setAllPatients(mapped); setAllPatients(mapped);
} catch (e: any) { } catch (e: any) {
@ -105,31 +79,32 @@ export default function PacientesPage() {
} }
}, []); }, []);
// 2. Efeito para aplicar filtros e calcular a lista filtrada (chama-se quando allPatients ou filtros mudam) // 2. Efeito para aplicar filtros e calcular a lista filtrada (chama-se quando allPatients ou filtros mudam)
useEffect(() => { useEffect(() => {
const filtered = allPatients.filter((patient) => { const filtered = allPatients.filter((patient) => {
// Filtro por termo de busca (Nome ou Telefone) // Filtro por termo de busca (Nome ou Telefone)
const matchesSearch = const matchesSearch =
patient.nome?.toLowerCase().includes(searchTerm.toLowerCase()) || patient.nome?.toLowerCase().includes(searchTerm.toLowerCase()) ||
patient.telefone?.includes(searchTerm); patient.telefone?.includes(searchTerm);
// Filtro por Convênio // Filtro por Convênio
const matchesConvenio = const matchesConvenio =
convenioFilter === "all" || patient.convenio === convenioFilter; convenioFilter === "all" ||
patient.convenio === convenioFilter;
// Filtro por VIP // Filtro por VIP
const matchesVip = const matchesVip =
vipFilter === "all" || vipFilter === "all" ||
(vipFilter === "vip" && patient.vip) || (vipFilter === "vip" && patient.vip) ||
(vipFilter === "regular" && !patient.vip); (vipFilter === "regular" && !patient.vip);
return matchesSearch && matchesConvenio && matchesVip; return matchesSearch && matchesConvenio && matchesVip;
}); });
setFilteredPatients(filtered); setFilteredPatients(filtered);
// Garante que a página atual seja válida após a filtragem // Garante que a página atual seja válida após a filtragem
setPage(1); setPage(1);
}, [allPatients, searchTerm, convenioFilter, vipFilter]); }, [allPatients, searchTerm, convenioFilter, vipFilter]);
// 3. Efeito inicial para buscar os pacientes // 3. Efeito inicial para buscar os pacientes
useEffect(() => { useEffect(() => {
@ -137,18 +112,18 @@ export default function PacientesPage() {
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, []); }, []);
// --- LÓGICA DE AÇÕES (DELETAR / VER DETALHES) --- // --- LÓGICA DE AÇÕES (DELETAR / VER DETALHES) ---
const openDetailsDialog = async (patientId: string) => { const openDetailsDialog = async (patientId: string) => {
setDetailsDialogOpen(true); setDetailsDialogOpen(true);
setPatientDetails(null); setPatientDetails(null);
try { try {
const res = await patientsService.getById(patientId); const res = await patientsService.getById(patientId);
setPatientDetails(Array.isArray(res) ? res[0] : res); // Supondo que retorne um array com um item setPatientDetails(Array.isArray(res) ? res[0] : res); // Supondo que retorne um array com um item
} catch (e: any) { } catch (e: any) {
setPatientDetails({ error: e?.message || "Erro ao buscar detalhes" }); setPatientDetails({ error: e?.message || "Erro ao buscar detalhes" });
} }
}; };
const handleDeletePatient = async (patientId: string) => { const handleDeletePatient = async (patientId: string) => {
try { try {
@ -192,19 +167,18 @@ export default function PacientesPage() {
</div> </div>
</div> </div>
{/* Bloco de Filtros (Responsividade APLICADA) */} {/* Bloco de Filtros (Responsividade APLICADA) */}
<div className="flex flex-wrap items-center gap-4 bg-card p-4 rounded-lg border border-border"> <div className="flex flex-wrap items-center gap-4 bg-card p-4 rounded-lg border border-border">
<Filter className="w-5 h-5 text-gray-400" /> <Filter className="w-5 h-5 text-gray-400" />
{/* Busca - Ocupa 100% no mobile, depois cresce */} {/* Busca - Ocupa 100% no mobile, depois cresce */}
<input <input
type="text" type="text"
placeholder="Buscar por nome ou telefone..." placeholder="Buscar por nome ou telefone..."
value={searchTerm} value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)} onChange={(e) => setSearchTerm(e.target.value)}
// w-full no mobile, depois flex-grow para ocupar o espaço disponível className="w-full sm:flex-grow sm:min-w-[150px] p-2 border rounded-md text-sm"
className="w-full sm:flex-grow sm:max-w-[300px] p-2 border rounded-md text-sm" />
/>
{/* Convênio - Ocupa a largura total em telas pequenas, depois se ajusta */} {/* Convênio - Ocupa a largura total em telas pequenas, depois se ajusta */}
<div className="flex items-center gap-2 w-full sm:w-auto sm:flex-grow sm:max-w-[200px]"> <div className="flex items-center gap-2 w-full sm:w-auto sm:flex-grow sm:max-w-[200px]">

View File

@ -41,8 +41,10 @@ export interface ButtonProps
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>( const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
({ className, variant, size, asChild = false, ...props }, ref) => { ({ className, variant, size, asChild = false, ...props }, ref) => {
const Comp = asChild ? Slot : 'button' const Comp = asChild ? Slot : 'button'
return ( return (
<Comp <Comp
data-slot="button"
className={cn(buttonVariants({ variant, size, className }))} className={cn(buttonVariants({ variant, size, className }))}
ref={ref} ref={ref}
{...props} {...props}