import { SearchableSelect } from '../components/SearchableSelect'; import { useEffect, useState } from 'react'; import type { FormEvent } from 'react'; import { Link, useSearchParams } from 'react-router'; import { PermissionGate } from '../auth/PermissionGate'; import { Alert, EmptyState, LoadingBlock, errorMessage } from '../components/Feedback'; import { Icon } from '../components/Icon'; import { SURVEY_CAMPAIGN_STATUSES, surveyCampaignStatusLabel, surveyStatusClass, } from '../features/surveys/surveyPresentation'; import { listSurveyCampaigns } from '../lib/api'; import type { PageMeta, SurveyCampaignListItem, SurveyCampaignStatus, } from '../lib/api'; import { formatDate } from '../lib/format'; export function SurveyCampaignsPage() { const [urlParams, setUrlParams] = useSearchParams(); const [campaigns, setCampaigns] = useState([]); const [meta, setMeta] = useState({ page: 1, pageSize: 25, total: 0, totalPages: 0 }); const [loading, setLoading] = useState(true); const [error, setError] = useState(''); const [draftSearch, setDraftSearch] = useState(urlParams.get('search') ?? ''); const search = urlParams.get('search') ?? ''; const rawStatus = urlParams.get('status') ?? ''; const status = SURVEY_CAMPAIGN_STATUSES.some((item) => item.value === rawStatus) ? rawStatus as SurveyCampaignStatus : ''; const page = Math.max(1, Number(urlParams.get('page') ?? 1) || 1); useEffect(() => { setLoading(true); setError(''); listSurveyCampaigns({ page, pageSize: 25, search, status }) .then((response) => { setCampaigns(response.data); setMeta(response.meta); }) .catch((requestError) => setError(errorMessage(requestError))) .finally(() => setLoading(false)); }, [page, search, status]); const updateFilter = (key: string, value: string) => { const next = new URLSearchParams(urlParams); value ? next.set(key, value) : next.delete(key); next.delete('page'); setUrlParams(next); }; const applySearch = (event: FormEvent) => { event.preventDefault(); updateFilter('search', draftSearch.trim()); }; const setPage = (value: number) => { const next = new URLSearchParams(urlParams); value > 1 ? next.set('page', String(value)) : next.delete('page'); setUrlParams(next); }; return
OPERACIÓN DE CAMPO

Relevamientos

Campañas planificadas sobre registros existentes de los inventarios.

Nueva campaña

Inventarios organizados por empresa. Las campañas organizan qué registros relevar, quién los atiende y su avance; no crean un inventario paralelo.

{error && {error}} {loading ? : campaigns.length === 0 ? :
{meta.total} campaña{meta.total === 1 ? '' : 's'}Página {page} de {Math.max(meta.totalPages, 1)}
{campaigns.map((campaign) => )}
CampañaEstadoAlcanceCoordinaciónFechas previstasAvance
{campaign.name}{campaign.code}
{surveyCampaignStatusLabel(campaign.status)}{campaign.scopeAsset ? {campaign.scopeAsset.name} : Todos los inventarios}{campaign.coordinator ? `${campaign.coordinator.firstName} ${campaign.coordinator.lastName}` : 'Sin asignar'}{formatDate(campaign.plannedStartAt)}hasta {formatDate(campaign.plannedEndAt)}
{campaign.completedCount + campaign.skippedCount}/{campaign.targetCount}
{meta.total ? `${(page - 1) * meta.pageSize + 1}–${Math.min(page * meta.pageSize, meta.total)} de ${meta.total}` : '0 resultados'}
}
; }