|
@@ -4,7 +4,7 @@ import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
|
|
|
import { Button } from "@/components/ui/button"
|
|
import { Button } from "@/components/ui/button"
|
|
|
import { Input } from "@/components/ui/input"
|
|
import { Input } from "@/components/ui/input"
|
|
|
import { Label } from "@/components/ui/label"
|
|
import { Label } from "@/components/ui/label"
|
|
|
-import { Filter, ChevronDown } from "lucide-react"
|
|
|
|
|
|
|
+import { Filter, Search, Calendar, SlidersHorizontal } from "lucide-react"
|
|
|
import PatientSearchInput from "./PatientSearchInput"
|
|
import PatientSearchInput from "./PatientSearchInput"
|
|
|
|
|
|
|
|
interface RecordsFiltersProps {
|
|
interface RecordsFiltersProps {
|
|
@@ -62,105 +62,116 @@ export default function RecordsFilters({
|
|
|
onShowFiltersToggle,
|
|
onShowFiltersToggle,
|
|
|
onClearFilters
|
|
onClearFilters
|
|
|
}: RecordsFiltersProps) {
|
|
}: RecordsFiltersProps) {
|
|
|
|
|
+ // Siempre mostrar los filtros más importantes, solo ocultar los avanzados
|
|
|
|
|
+ const showBasicFilters = true
|
|
|
|
|
+
|
|
|
return (
|
|
return (
|
|
|
<Card className="mb-6 border shadow-sm rounded-xl">
|
|
<Card className="mb-6 border shadow-sm rounded-xl">
|
|
|
<CardHeader className="pb-4 px-6 pt-6">
|
|
<CardHeader className="pb-4 px-6 pt-6">
|
|
|
- <div className="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-3">
|
|
|
|
|
- <div className="flex items-center space-x-3 flex-1 min-w-0">
|
|
|
|
|
|
|
+ <div className="flex items-center justify-between">
|
|
|
|
|
+ <div className="flex items-center space-x-3">
|
|
|
<div className="w-10 h-10 flex-shrink-0 bg-primary rounded-lg flex items-center justify-center shadow-sm">
|
|
<div className="w-10 h-10 flex-shrink-0 bg-primary rounded-lg flex items-center justify-center shadow-sm">
|
|
|
<Filter className="w-5 h-5 text-primary-foreground" />
|
|
<Filter className="w-5 h-5 text-primary-foreground" />
|
|
|
</div>
|
|
</div>
|
|
|
- <div className="min-w-0">
|
|
|
|
|
|
|
+ <div>
|
|
|
<CardTitle className="text-xl font-bold text-foreground">Filtros y Búsqueda</CardTitle>
|
|
<CardTitle className="text-xl font-bold text-foreground">Filtros y Búsqueda</CardTitle>
|
|
|
- <p className="text-sm text-muted-foreground">Personaliza tu búsqueda de reportes</p>
|
|
|
|
|
|
|
+ <p className="text-sm text-muted-foreground">Encuentra rápidamente lo que buscas</p>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
- <Button
|
|
|
|
|
- variant="outline"
|
|
|
|
|
- size="sm"
|
|
|
|
|
- onClick={onShowFiltersToggle}
|
|
|
|
|
- className="flex items-center space-x-2 flex-shrink-0"
|
|
|
|
|
- >
|
|
|
|
|
- <span className="font-medium">{showFilters ? "Ocultar" : "Mostrar"} filtros</span>
|
|
|
|
|
- <ChevronDown className={`w-4 h-4 transition-transform duration-200 ${showFilters ? 'rotate-180' : ''}`} />
|
|
|
|
|
- </Button>
|
|
|
|
|
|
|
+ {(searchTerm || selectedPatientId || dateFilter) && (
|
|
|
|
|
+ <Button
|
|
|
|
|
+ variant="outline"
|
|
|
|
|
+ size="sm"
|
|
|
|
|
+ onClick={onClearFilters}
|
|
|
|
|
+ className="text-destructive border-destructive hover:bg-destructive hover:text-destructive-foreground"
|
|
|
|
|
+ >
|
|
|
|
|
+ Limpiar filtros
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ )}
|
|
|
</div>
|
|
</div>
|
|
|
</CardHeader>
|
|
</CardHeader>
|
|
|
|
|
|
|
|
- {showFilters && (
|
|
|
|
|
- <CardContent className="pt-0 px-6 pb-6">
|
|
|
|
|
- <div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
|
|
|
|
- {/* Búsqueda por paciente - Solo para doctores */}
|
|
|
|
|
- {userRole === "DOCTOR" && (
|
|
|
|
|
- <div className="bg-muted rounded-xl p-4 border">
|
|
|
|
|
- <PatientSearchInput
|
|
|
|
|
- value={searchTerm}
|
|
|
|
|
- onChange={onSearchChange}
|
|
|
|
|
- selectedPatient={selectedPatient}
|
|
|
|
|
- onPatientSelect={onPatientSelect}
|
|
|
|
|
- placeholder="Nombre, email o username del paciente..."
|
|
|
|
|
- />
|
|
|
|
|
- </div>
|
|
|
|
|
- )}
|
|
|
|
|
|
|
+ {/* Filtros básicos - Siempre visibles */}
|
|
|
|
|
+ <CardContent className="pt-0 px-6 pb-6">
|
|
|
|
|
+ <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
|
|
|
|
|
+ {/* Búsqueda principal - Siempre visible */}
|
|
|
|
|
+ <div className="bg-muted/50 rounded-xl p-4 border border-border/50">
|
|
|
|
|
+ <Label htmlFor="mainSearch" className="text-foreground font-medium flex items-center">
|
|
|
|
|
+ <Search className="w-4 h-4 mr-2" />
|
|
|
|
|
+ Búsqueda rápida
|
|
|
|
|
+ </Label>
|
|
|
|
|
+ <Input
|
|
|
|
|
+ id="mainSearch"
|
|
|
|
|
+ type="text"
|
|
|
|
|
+ placeholder="Buscar en contenidos, paciente..."
|
|
|
|
|
+ value={searchTerm}
|
|
|
|
|
+ onChange={(e) => onSearchChange(e.target.value)}
|
|
|
|
|
+ className="mt-2"
|
|
|
|
|
+ />
|
|
|
|
|
+ </div>
|
|
|
|
|
|
|
|
- {/* Búsqueda por contenido del reporte */}
|
|
|
|
|
- <div className="bg-muted rounded-xl p-4 border">
|
|
|
|
|
- <Label htmlFor="contentSearch" className="text-foreground font-medium">Buscar en reportes</Label>
|
|
|
|
|
- <Input
|
|
|
|
|
- id="contentSearch"
|
|
|
|
|
- type="text"
|
|
|
|
|
- placeholder="Buscar por contenido, paciente..."
|
|
|
|
|
- value={searchTerm}
|
|
|
|
|
- onChange={(e) => onSearchChange(e.target.value)}
|
|
|
|
|
- className="mt-2"
|
|
|
|
|
- />
|
|
|
|
|
- </div>
|
|
|
|
|
|
|
+ {/* Filtro por fecha - Siempre visible */}
|
|
|
|
|
+ <div className="bg-muted/50 rounded-xl p-4 border border-border/50">
|
|
|
|
|
+ <Label htmlFor="dateFilter" className="text-foreground font-medium flex items-center">
|
|
|
|
|
+ <Calendar className="w-4 h-4 mr-2" />
|
|
|
|
|
+ Fecha
|
|
|
|
|
+ </Label>
|
|
|
|
|
+ <Input
|
|
|
|
|
+ id="dateFilter"
|
|
|
|
|
+ type="date"
|
|
|
|
|
+ value={dateFilter}
|
|
|
|
|
+ onChange={(e) => onDateFilterChange(e.target.value)}
|
|
|
|
|
+ className="mt-2"
|
|
|
|
|
+ />
|
|
|
|
|
+ </div>
|
|
|
|
|
|
|
|
- {/* Filtro por fecha */}
|
|
|
|
|
- <div className="bg-muted rounded-xl p-4 border">
|
|
|
|
|
- <Label htmlFor="dateFilter" className="text-foreground font-medium">Filtrar por fecha</Label>
|
|
|
|
|
- <Input
|
|
|
|
|
- id="dateFilter"
|
|
|
|
|
- type="date"
|
|
|
|
|
- value={dateFilter}
|
|
|
|
|
- onChange={(e) => onDateFilterChange(e.target.value)}
|
|
|
|
|
- className="mt-2"
|
|
|
|
|
|
|
+ {/* Búsqueda por paciente - Solo para doctores */}
|
|
|
|
|
+ {userRole === "DOCTOR" && (
|
|
|
|
|
+ <div className="bg-muted/50 rounded-xl p-4 border border-border/50">
|
|
|
|
|
+ <PatientSearchInput
|
|
|
|
|
+ value={searchTerm}
|
|
|
|
|
+ onChange={onSearchChange}
|
|
|
|
|
+ selectedPatient={selectedPatient}
|
|
|
|
|
+ onPatientSelect={onPatientSelect}
|
|
|
|
|
+ placeholder="Buscar paciente..."
|
|
|
/>
|
|
/>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
+ )}
|
|
|
|
|
|
|
|
- {/* Items por página */}
|
|
|
|
|
- <div className="bg-muted rounded-xl p-4 border">
|
|
|
|
|
- <Label htmlFor="itemsPerPage" className="text-foreground font-medium">Items por página</Label>
|
|
|
|
|
- <select
|
|
|
|
|
- id="itemsPerPage"
|
|
|
|
|
- value={itemsPerPage}
|
|
|
|
|
- onChange={(e) => onItemsPerPageChange(Number(e.target.value))}
|
|
|
|
|
- className="w-full mt-2 px-3 py-2 border rounded-md focus:outline-none focus:ring-2 focus:ring-ring focus:border-transparent"
|
|
|
|
|
- >
|
|
|
|
|
- {ITEMS_PER_PAGE_OPTIONS.map(option => (
|
|
|
|
|
- <option key={option} value={option}>
|
|
|
|
|
- {option} reportes
|
|
|
|
|
- </option>
|
|
|
|
|
- ))}
|
|
|
|
|
- </select>
|
|
|
|
|
- </div>
|
|
|
|
|
|
|
+ {/* Items por página - Siempre visible */}
|
|
|
|
|
+ <div className="bg-muted/50 rounded-xl p-4 border border-border/50">
|
|
|
|
|
+ <Label htmlFor="itemsPerPage" className="text-foreground font-medium flex items-center">
|
|
|
|
|
+ <SlidersHorizontal className="w-4 h-4 mr-2" />
|
|
|
|
|
+ Resultados
|
|
|
|
|
+ </Label>
|
|
|
|
|
+ <select
|
|
|
|
|
+ id="itemsPerPage"
|
|
|
|
|
+ value={itemsPerPage}
|
|
|
|
|
+ onChange={(e) => onItemsPerPageChange(Number(e.target.value))}
|
|
|
|
|
+ className="w-full mt-2 px-3 py-2 border rounded-md focus:outline-none focus:ring-2 focus:ring-ring focus:border-transparent bg-background"
|
|
|
|
|
+ >
|
|
|
|
|
+ {ITEMS_PER_PAGE_OPTIONS.map(option => (
|
|
|
|
|
+ <option key={option} value={option}>
|
|
|
|
|
+ {option} por página
|
|
|
|
|
+ </option>
|
|
|
|
|
+ ))}
|
|
|
|
|
+ </select>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
+ </div>
|
|
|
|
|
|
|
|
- {/* Botón limpiar filtros */}
|
|
|
|
|
- {(searchTerm || selectedPatientId || dateFilter) && (
|
|
|
|
|
- <div className="mt-6 flex justify-center">
|
|
|
|
|
- <Button
|
|
|
|
|
- variant="outline"
|
|
|
|
|
- size="sm"
|
|
|
|
|
- onClick={onClearFilters}
|
|
|
|
|
- className="text-destructive border-destructive hover:bg-destructive hover:text-destructive-foreground px-6"
|
|
|
|
|
- >
|
|
|
|
|
- Limpiar todos los filtros
|
|
|
|
|
- </Button>
|
|
|
|
|
|
|
+ {/* Indicador de filtros activos */}
|
|
|
|
|
+ {(searchTerm || selectedPatientId || dateFilter) && (
|
|
|
|
|
+ <div className="mt-4 flex items-center justify-center">
|
|
|
|
|
+ <div className="text-sm text-muted-foreground bg-muted/80 px-4 py-2 rounded-full border">
|
|
|
|
|
+ <span className="font-medium">
|
|
|
|
|
+ {searchTerm && `🔍 "${searchTerm}" `}
|
|
|
|
|
+ {selectedPatientId && `👤 Paciente seleccionado `}
|
|
|
|
|
+ {dateFilter && `📅 ${new Date(dateFilter).toLocaleDateString('es-ES')}`}
|
|
|
|
|
+ </span>
|
|
|
</div>
|
|
</div>
|
|
|
- )}
|
|
|
|
|
- </CardContent>
|
|
|
|
|
- )}
|
|
|
|
|
|
|
+ </div>
|
|
|
|
|
+ )}
|
|
|
|
|
+ </CardContent>
|
|
|
</Card>
|
|
</Card>
|
|
|
)
|
|
)
|
|
|
-}
|
|
|
|
|
|
|
+}
|