feat(rennmausakte): Datenherkunft/Nachverfolgung pro Rennmaus
Neuer „Datenherkunft"-Button in der Rennmausakte öffnet einen Dialog, der zeigt, aus welchen Quellen der Eintrag erzeugt wurde: Quelldateien (Stammbäume + Wurfchronik), Anzahl zusammengeführter Datensätze, Eltern-Herleitung (Methode/Konfidenz) und Hinweise (z. B. „per manueller Entscheidung zugeordnet", „Konflikt gelöst", „aus N Datensätzen zusammengeführt"). Import: build_provenance() in merge_and_resolve.py sammelt die Herkunft über alle deduplizierten Datensätze und schreibt sie als Provenance-JSON je Tier in resolved_import.json. Backend: Gerbil.Provenance (nullable text) + Migration AddGerbilProvenance, gemappt im Ingest und im GerbilDto zurückgegeben. Frontend: ProvenanceDialog + Typen + Strings. Tests: Ingest-Round-trip (vorhanden/abwesend), e2e provenance.spec.ts. dotnet(212)/vitest(129)/playwright/tsc/eslint grün. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -14,6 +14,7 @@ import GerbilHealthTab from '../components/GerbilHealthTab'
|
||||
import GerbilPhotosTab from '../components/GerbilPhotosTab'
|
||||
import GerbilProfilePhoto from '../components/GerbilProfilePhoto'
|
||||
import GerbilWeightTab from '../components/GerbilWeightTab'
|
||||
import ProvenanceDialog from '../components/ProvenanceDialog'
|
||||
import ReportErrorDialog from '../components/ReportErrorDialog'
|
||||
import { useGerbilName } from '../components/breederSuffix'
|
||||
import { useToast } from '../components/toast'
|
||||
@@ -59,6 +60,7 @@ export default function GerbilDetailPage() {
|
||||
const { id = '' } = useParams()
|
||||
const [tab, setTab] = useState<DetailTab>('photos')
|
||||
const [reportOpen, setReportOpen] = useState(false)
|
||||
const [provenanceOpen, setProvenanceOpen] = useState(false)
|
||||
|
||||
const gerbil = useApi(() => getGerbil(id), [id])
|
||||
const forSale = useMutation(() => updateGerbil(id, { status: 'ForSale' }))
|
||||
@@ -258,6 +260,9 @@ export default function GerbilDetailPage() {
|
||||
{de.pages.vertraege.wizard.title}
|
||||
</Link>
|
||||
)}
|
||||
<button type="button" className="ak-btn" onClick={() => setProvenanceOpen(true)}>
|
||||
{de.provenance.button}
|
||||
</button>
|
||||
<button type="button" className="ak-btn" onClick={() => setReportOpen(true)}>
|
||||
{de.feedback.button}
|
||||
</button>
|
||||
@@ -482,6 +487,12 @@ export default function GerbilDetailPage() {
|
||||
onClose={() => setReportOpen(false)}
|
||||
context={{ context: 'gerbil-detail', gerbilId: g.id, entityName: g.name || de.pages.gerbils.nameless }}
|
||||
/>
|
||||
|
||||
<ProvenanceDialog
|
||||
open={provenanceOpen}
|
||||
onClose={() => setProvenanceOpen(false)}
|
||||
provenance={g.provenance}
|
||||
/>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user