agregar fiiltros de busqueda en el front
This commit is contained in:
@@ -1462,6 +1462,8 @@ function ChecklistsTab({ checklists, user, onChecklistCreated, onStartInspection
|
|||||||
const [creating, setCreating] = useState(false)
|
const [creating, setCreating] = useState(false)
|
||||||
const [updating, setUpdating] = useState(false)
|
const [updating, setUpdating] = useState(false)
|
||||||
const [mechanics, setMechanics] = useState([])
|
const [mechanics, setMechanics] = useState([])
|
||||||
|
const [searchTerm, setSearchTerm] = useState('')
|
||||||
|
const [aiModeFilter, setAiModeFilter] = useState('all') // all, off, optional, required
|
||||||
const [formData, setFormData] = useState({
|
const [formData, setFormData] = useState({
|
||||||
name: '',
|
name: '',
|
||||||
description: '',
|
description: '',
|
||||||
@@ -1497,6 +1499,19 @@ function ChecklistsTab({ checklists, user, onChecklistCreated, onStartInspection
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Filtrar checklists
|
||||||
|
const filteredChecklists = checklists.filter(checklist => {
|
||||||
|
const matchesSearch =
|
||||||
|
checklist.name?.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||||
|
checklist.description?.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||||
|
checklist.id?.toString().includes(searchTerm)
|
||||||
|
|
||||||
|
const matchesAiMode =
|
||||||
|
aiModeFilter === 'all' || checklist.ai_mode === aiModeFilter
|
||||||
|
|
||||||
|
return matchesSearch && matchesAiMode
|
||||||
|
})
|
||||||
|
|
||||||
const handleCreate = async (e) => {
|
const handleCreate = async (e) => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
setCreating(true)
|
setCreating(true)
|
||||||
@@ -1581,6 +1596,41 @@ function ChecklistsTab({ checklists, user, onChecklistCreated, onStartInspection
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* Buscador y Filtros */}
|
||||||
|
{checklists.length > 0 && (
|
||||||
|
<div className="mb-6 space-y-4">
|
||||||
|
<div className="flex gap-4 flex-wrap">
|
||||||
|
{/* Buscador */}
|
||||||
|
<div className="flex-1 min-w-[300px]">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder="Buscar por nombre, descripción o ID..."
|
||||||
|
value={searchTerm}
|
||||||
|
onChange={(e) => setSearchTerm(e.target.value)}
|
||||||
|
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Filtro de Modo IA */}
|
||||||
|
<select
|
||||||
|
value={aiModeFilter}
|
||||||
|
onChange={(e) => setAiModeFilter(e.target.value)}
|
||||||
|
className="px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||||||
|
>
|
||||||
|
<option value="all">Todos los modos IA</option>
|
||||||
|
<option value="off">Sin IA</option>
|
||||||
|
<option value="optional">IA Opcional</option>
|
||||||
|
<option value="required">IA Requerida</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Contador de resultados */}
|
||||||
|
<div className="text-sm text-gray-600">
|
||||||
|
Mostrando {filteredChecklists.length} de {checklists.length} checklists
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{checklists.length === 0 ? (
|
{checklists.length === 0 ? (
|
||||||
<div className="text-center py-12">
|
<div className="text-center py-12">
|
||||||
{user.role === 'admin' ? (
|
{user.role === 'admin' ? (
|
||||||
@@ -1603,8 +1653,21 @@ function ChecklistsTab({ checklists, user, onChecklistCreated, onStartInspection
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
) : filteredChecklists.length === 0 ? (
|
||||||
|
<div className="text-center py-12">
|
||||||
|
<p className="text-gray-500">No se encontraron checklists con los filtros aplicados</p>
|
||||||
|
<button
|
||||||
|
onClick={() => {
|
||||||
|
setSearchTerm('')
|
||||||
|
setAiModeFilter('all')
|
||||||
|
}}
|
||||||
|
className="mt-4 text-blue-600 hover:text-blue-700 underline"
|
||||||
|
>
|
||||||
|
Limpiar filtros
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
) : (
|
) : (
|
||||||
checklists.map((checklist) => (
|
filteredChecklists.map((checklist) => (
|
||||||
<div key={checklist.id} className="border border-gray-200 rounded-lg p-4 hover:shadow-md transition">
|
<div key={checklist.id} className="border border-gray-200 rounded-lg p-4 hover:shadow-md transition">
|
||||||
<div className="flex justify-between items-start">
|
<div className="flex justify-between items-start">
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
@@ -2670,6 +2733,26 @@ function InspectionDetailModal({ inspection, user, onClose, onUpdate }) {
|
|||||||
|
|
||||||
function InspectionsTab({ inspections, user, onUpdate }) {
|
function InspectionsTab({ inspections, user, onUpdate }) {
|
||||||
const [selectedInspection, setSelectedInspection] = useState(null)
|
const [selectedInspection, setSelectedInspection] = useState(null)
|
||||||
|
const [searchTerm, setSearchTerm] = useState('')
|
||||||
|
const [statusFilter, setStatusFilter] = useState('all') // all, completed, draft
|
||||||
|
|
||||||
|
// Filtrar inspecciones
|
||||||
|
const filteredInspections = inspections.filter(inspection => {
|
||||||
|
const matchesSearch =
|
||||||
|
inspection.vehicle_plate?.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||||
|
inspection.vehicle_brand?.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||||
|
inspection.vehicle_model?.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||||
|
inspection.client_name?.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||||
|
inspection.or_number?.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||||
|
inspection.id?.toString().includes(searchTerm)
|
||||||
|
|
||||||
|
const matchesStatus =
|
||||||
|
statusFilter === 'all' ||
|
||||||
|
(statusFilter === 'completed' && inspection.status === 'completed') ||
|
||||||
|
(statusFilter === 'draft' && inspection.status !== 'completed')
|
||||||
|
|
||||||
|
return matchesSearch && matchesStatus
|
||||||
|
})
|
||||||
|
|
||||||
if (inspections.length === 0) {
|
if (inspections.length === 0) {
|
||||||
return (
|
return (
|
||||||
@@ -2682,8 +2765,55 @@ function InspectionsTab({ inspections, user, onUpdate }) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="space-y-4">
|
{/* Buscador y Filtros */}
|
||||||
{inspections.map((inspection) => (
|
<div className="mb-6 space-y-4">
|
||||||
|
<div className="flex gap-4 flex-wrap">
|
||||||
|
{/* Buscador */}
|
||||||
|
<div className="flex-1 min-w-[300px]">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder="Buscar por placa, marca, modelo, cliente, OR o ID..."
|
||||||
|
value={searchTerm}
|
||||||
|
onChange={(e) => setSearchTerm(e.target.value)}
|
||||||
|
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Filtro de Estado */}
|
||||||
|
<select
|
||||||
|
value={statusFilter}
|
||||||
|
onChange={(e) => setStatusFilter(e.target.value)}
|
||||||
|
className="px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
||||||
|
>
|
||||||
|
<option value="all">Todos los estados</option>
|
||||||
|
<option value="completed">Completadas</option>
|
||||||
|
<option value="draft">Borradores</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Contador de resultados */}
|
||||||
|
<div className="text-sm text-gray-600">
|
||||||
|
Mostrando {filteredInspections.length} de {inspections.length} inspecciones
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Lista de Inspecciones */}
|
||||||
|
{filteredInspections.length === 0 ? (
|
||||||
|
<div className="text-center py-12">
|
||||||
|
<p className="text-gray-500">No se encontraron inspecciones con los filtros aplicados</p>
|
||||||
|
<button
|
||||||
|
onClick={() => {
|
||||||
|
setSearchTerm('')
|
||||||
|
setStatusFilter('all')
|
||||||
|
}}
|
||||||
|
className="mt-4 text-blue-600 hover:text-blue-700 underline"
|
||||||
|
>
|
||||||
|
Limpiar filtros
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="space-y-4">
|
||||||
|
{filteredInspections.map((inspection) => (
|
||||||
<div key={inspection.id} className="border border-gray-200 rounded-lg p-4 hover:shadow-md transition">
|
<div key={inspection.id} className="border border-gray-200 rounded-lg p-4 hover:shadow-md transition">
|
||||||
<div className="flex justify-between items-start">
|
<div className="flex justify-between items-start">
|
||||||
<div>
|
<div>
|
||||||
@@ -2725,7 +2855,8 @@ function InspectionsTab({ inspections, user, onUpdate }) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* Modal de Detalle */}
|
{/* Modal de Detalle */}
|
||||||
{selectedInspection && (
|
{selectedInspection && (
|
||||||
|
|||||||
Reference in New Issue
Block a user