chore: import DH V2 D5.6.4 production baseline

This commit is contained in:
DH V2
2026-09-05 10:12:35 -03:00
commit 82213e72f5
757 changed files with 84218 additions and 0 deletions
@@ -0,0 +1,66 @@
import { useEffect, useState } from 'react';
import { Alert, LoadingBlock, errorMessage } from '../../components/Feedback';
import { Icon } from '../../components/Icon';
import {
getAssetVersion,
listAssetVersionTimeline,
} from '../../lib/api';
import type {
AssetVersionDetail,
AssetVersionSummary,
} from '../../lib/api';
import { formatDate } from '../../lib/format';
import { AssetVersionDrawer } from './AssetVersionDrawer';
import {
assetVersionChangeLabel,
assetVersionFieldLabel,
} from './assetVersionPresentation';
export function AssetHistoryPanel({
assetId,
refreshKey,
}: {
assetId: string;
refreshKey: number;
}) {
const [versions, setVersions] = useState<AssetVersionSummary[]>([]);
const [total, setTotal] = useState(0);
const [loading, setLoading] = useState(true);
const [error, setError] = useState('');
const [detail, setDetail] = useState<AssetVersionDetail | null>(null);
const [detailLoading, setDetailLoading] = useState(false);
useEffect(() => {
setLoading(true);
setError('');
listAssetVersionTimeline(assetId, { pageSize: 10 })
.then((response) => {
setVersions(response.data);
setTotal(response.meta.total);
})
.catch((requestError) => setError(errorMessage(requestError)))
.finally(() => setLoading(false));
}, [assetId, refreshKey]);
const open = async (version: AssetVersionSummary) => {
setDetail(null);
setDetailLoading(true);
setError('');
try {
setDetail(await getAssetVersion(version.assetId, version.versionNumber));
} catch (requestError) {
setError(errorMessage(requestError));
} finally {
setDetailLoading(false);
}
};
return <article className="panel asset-history-panel">
<div className="panel-heading"><div><span className="eyebrow">TRAZABILIDAD TEMPORAL</span><h2>Historial del registro</h2></div><span className="count-pill">{total} versión{total === 1 ? '' : 'es'}</span></div>
<p className="section-copy">Cada cambio conserva una copia completa e inmutable del registro, sus atributos y su ubicación.</p>
{error && <Alert>{error}</Alert>}
{loading ? <LoadingBlock label="Cargando historial…" /> : <div className="asset-timeline">{versions.map((version) => <button type="button" className="timeline-entry" key={version.id} onClick={() => open(version)}><span className={`timeline-dot ${version.isCurrent ? 'current' : ''}`} /><span><strong>v{version.versionNumber} · {assetVersionChangeLabel(version.changeType)}</strong><small>{formatDate(version.occurredAt)} · {version.actorUsername ?? 'Sistema'}</small><span className="tag-list">{version.changedFields.slice(0, 4).map((field) => <em className="tag" key={field}>{assetVersionFieldLabel(field)}</em>)}</span></span><Icon name="chevron" size={16} /></button>)}</div>}
{!loading && total > versions.length && <p className="history-limit-note">Se muestran las 10 versiones más recientes. El historial completo está disponible en la sección Historial.</p>}
{(detailLoading || detail) && <AssetVersionDrawer detail={detail} loading={detailLoading} onClose={() => setDetail(null)} />}
</article>;
}