92 lines
4.0 KiB
TypeScript
92 lines
4.0 KiB
TypeScript
import { SearchableSelect } from './SearchableSelect';
|
|
import { useEffect, useMemo, useState } from 'react';
|
|
import type { FormEvent } from 'react';
|
|
import { Link, useNavigate } from 'react-router';
|
|
import { useAuth } from '../auth/AuthContext';
|
|
import { useOperationalContext } from '../context/OperationalContext';
|
|
import { listCompaniesForArea, listOperationalAreas } from '../lib/api';
|
|
import type { OperationalAssetSummary } from '../lib/api';
|
|
import { Icon } from './Icon';
|
|
|
|
export function OperationalContextBar() {
|
|
const navigate = useNavigate();
|
|
const { hasPermission } = useAuth();
|
|
const { areaId, companyId, setAreaId, setCompanyId, clearContext } = useOperationalContext();
|
|
const [areas, setAreas] = useState<OperationalAssetSummary[]>([]);
|
|
const [companies, setCompanies] = useState<OperationalAssetSummary[]>([]);
|
|
const [search, setSearch] = useState('');
|
|
|
|
const canReadInventory = hasPermission('assets.read');
|
|
const canReadInspections = hasPermission('inspections.read');
|
|
|
|
useEffect(() => {
|
|
if (!canReadInventory && !canReadInspections) return;
|
|
listOperationalAreas().then(setAreas).catch(() => setAreas([]));
|
|
}, [canReadInventory, canReadInspections]);
|
|
|
|
useEffect(() => {
|
|
if (!areaId) {
|
|
setCompanies([]);
|
|
if (companyId) setCompanyId('');
|
|
return;
|
|
}
|
|
listCompaniesForArea(areaId)
|
|
.then((rows) => {
|
|
setCompanies(rows);
|
|
if (companyId && !rows.some((item) => item.id === companyId)) setCompanyId('');
|
|
})
|
|
.catch(() => setCompanies([]));
|
|
}, [areaId, companyId, setCompanyId]);
|
|
|
|
const selectedArea = useMemo(() => areas.find((item) => item.id === areaId) ?? null, [areas, areaId]);
|
|
const selectedCompany = useMemo(() => companies.find((item) => item.id === companyId) ?? null, [companies, companyId]);
|
|
|
|
const submitSearch = (event: FormEvent) => {
|
|
event.preventDefault();
|
|
const term = search.trim();
|
|
if (!term || !canReadInventory) return;
|
|
navigate(`/inventarios?view=list&search=${encodeURIComponent(term)}`);
|
|
};
|
|
|
|
if (!canReadInventory && !canReadInspections) return null;
|
|
|
|
return <section className="operational-context-bar" aria-label="Contexto de trabajo">
|
|
<div className="operational-context-summary">
|
|
<span className="operational-context-icon"><Icon name="layers" size={17} /></span>
|
|
<div>
|
|
<small>CONTEXTO DE TRABAJO</small>
|
|
<strong>{selectedArea ? selectedArea.name : 'Todas las Áreas'}{selectedCompany ? ` · ${selectedCompany.name}` : ''}</strong>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="operational-context-selectors">
|
|
<label>
|
|
<span>Área</span>
|
|
<SearchableSelect value={areaId} onChange={(event) => setAreaId(event.target.value)}>
|
|
<option value="">Todas las Áreas</option>
|
|
{areas.map((area) => <option key={area.id} value={area.id}>{area.name}</option>)}
|
|
</SearchableSelect>
|
|
</label>
|
|
<label>
|
|
<span>Operadora</span>
|
|
<SearchableSelect value={companyId} disabled={!areaId} onChange={(event) => setCompanyId(event.target.value)}>
|
|
<option value="">{areaId ? 'Todas las Operadoras' : 'Primero elegí un Área'}</option>
|
|
{companies.map((company) => <option key={company.id} value={company.id}>{company.name}</option>)}
|
|
</SearchableSelect>
|
|
</label>
|
|
</div>
|
|
|
|
{canReadInventory && <form className="operational-context-search" onSubmit={submitSearch}>
|
|
<Icon name="search" size={16} />
|
|
<input value={search} onChange={(event) => setSearch(event.target.value)} placeholder="Buscar en el Inventario…" />
|
|
<button type="submit">Buscar</button>
|
|
</form>}
|
|
|
|
<div className="operational-context-actions">
|
|
{canReadInventory && <Link className="button secondary compact" to="/inventarios">Inventario</Link>}
|
|
{canReadInspections && <Link className="button secondary compact" to="/inspecciones">Inspecciones</Link>}
|
|
{(areaId || companyId) && <button type="button" className="button text compact" onClick={clearContext}>Ver todo</button>}
|
|
</div>
|
|
</section>;
|
|
}
|