Merge feature/export-1: Datenexport (zip JSON+German CSVs) on /einstellungen + CI flake-cap [god-QA pending result-gate]

# Conflicts:
#	GerbilManager.Tests/GerbilManager.Tests.csproj
#	GerbilManagerWebAPI/Program.cs
#	gerbil-manager-web/src/App.tsx
#	gerbil-manager-web/src/components/AppShell.tsx
#	gerbil-manager-web/src/pages/EinstellungenPage.tsx
This commit is contained in:
2026-06-06 08:06:38 +02:00
10 changed files with 488 additions and 3 deletions

View File

@@ -0,0 +1,21 @@
/**
* EXPORT-1: Datenexport-Karte (auf /einstellungen) — lädt GET /export als Zip.
* Schlichter Anker-Download (kein fetch/Blob nötig); der Server setzt
* Content-Disposition mit Datumsdateinamen.
*/
import { API_BASE_URL } from '../api/client'
import { de } from '../strings/de'
export default function DatenexportCard() {
const t = de.pages.datenexport
return (
<section>
<h3>{t.title}</h3>
<p className="muted">{t.intro}</p>
<p className="muted">{t.photoNote}</p>
<a className="btn btn--primary" href={`${API_BASE_URL}/export`} download>
{t.button}
</a>
</section>
)
}

View File

@@ -13,6 +13,8 @@ import {
type BreederProfile,
} from '../api/settings'
import { useApi, useMutation } from '../hooks/useApi'
// EXPORT-1 (Oscar): Datenexport-Karte
import DatenexportCard from '../components/DatenexportCard'
export default function EinstellungenPage() {
const t = de.pages.einstellungen
@@ -95,6 +97,8 @@ export default function EinstellungenPage() {
{saved && <span className="muted">{tz.saved}</span>}
</div>
</form>
<DatenexportCard />
</section>
)
}

View File

@@ -565,6 +565,15 @@ export const de = {
},
},
},
// ── EXPORT-1 (Oscar): Datenexport (Karte auf /einstellungen) ──
datenexport: {
title: 'Datenexport',
intro:
'Sicherung deiner Daten — alle Tiere, Würfe und Kontakte als Tabellen (CSV für Excel) plus eine vollständige Datensicherung (JSON), gebündelt als Zip.',
button: 'Export herunterladen',
photoNote:
'Fotos sind nicht enthalten — sie liegen als Bilddateien im Datenordner der Anwendung und können von dort gesichert werden.',
},
},
// ── HELP-1: In-App-Anleitung ──
hilfe: {