diff --git a/app/package-lock.json b/app/package-lock.json index 767fea8..dad8bd4 100644 --- a/app/package-lock.json +++ b/app/package-lock.json @@ -9,6 +9,7 @@ "version": "0.1.0", "dependencies": { "ical-generator": "^10.2.0", + "papaparse": "^5.5.3", "pocketbase": "^0.26.9", "rrule": "^2.8.1", "web-push": "^3.6.7" @@ -17,6 +18,7 @@ "@sveltejs/adapter-node": "^5.5.4", "@sveltejs/kit": "^2.57.0", "@sveltejs/vite-plugin-svelte": "^7.0.0", + "@types/papaparse": "^5.5.2", "@types/web-push": "^3.6.4", "svelte": "^5.55.2", "svelte-check": "^4.4.6", @@ -2655,6 +2657,16 @@ "undici-types": ">=7.24.0 <7.24.7" } }, + "node_modules/@types/papaparse": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/@types/papaparse/-/papaparse-5.5.2.tgz", + "integrity": "sha512-gFnFp/JMzLHCwRf7tQHrNnfhN4eYBVYYI897CGX4MY1tzY9l2aLkVyx2IlKZ/SAqDbB3I1AOZW5gTMGGsqWliA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/resolve": { "version": "1.20.2", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", @@ -5090,6 +5102,12 @@ "dev": true, "license": "BlueOak-1.0.0" }, + "node_modules/papaparse": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/papaparse/-/papaparse-5.5.3.tgz", + "integrity": "sha512-5QvjGxYVjxO59MGU2lHVYpRWBBtKHnlIAcSe1uNFCkkptUh63NFRj0FJQm7nR67puEruUci/ZkjmEFrjCAyP4A==", + "license": "MIT" + }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", diff --git a/app/package.json b/app/package.json index fd9187a..3baa302 100644 --- a/app/package.json +++ b/app/package.json @@ -15,6 +15,7 @@ "@sveltejs/adapter-node": "^5.5.4", "@sveltejs/kit": "^2.57.0", "@sveltejs/vite-plugin-svelte": "^7.0.0", + "@types/papaparse": "^5.5.2", "@types/web-push": "^3.6.4", "svelte": "^5.55.2", "svelte-check": "^4.4.6", @@ -26,6 +27,7 @@ }, "dependencies": { "ical-generator": "^10.2.0", + "papaparse": "^5.5.3", "pocketbase": "^0.26.9", "rrule": "^2.8.1", "web-push": "^3.6.7" diff --git a/app/src/routes/(app)/einstellungen/+page.svelte b/app/src/routes/(app)/einstellungen/+page.svelte index acc793b..fb98046 100644 --- a/app/src/routes/(app)/einstellungen/+page.svelte +++ b/app/src/routes/(app)/einstellungen/+page.svelte @@ -330,6 +330,10 @@
+ Import / Export + + + {/if} @@ -482,6 +486,14 @@ cursor: pointer; align-self: flex-start; } + .btn-importexport { + display: block; width: 100%; padding: 0.75rem; + background: none; border: 1.5px solid #e2e8f0; border-radius: 8px; + font-size: 0.95rem; color: #1e40af; text-align: center; + text-decoration: none; margin-bottom: 0; + } + .btn-importexport:hover { border-color: #1e40af; background: #f0f9ff; } + .btn-logout { width: 100%; padding: 0.75rem; diff --git a/app/src/routes/(app)/import-export/+page.svelte b/app/src/routes/(app)/import-export/+page.svelte new file mode 100644 index 0000000..dd8c60c --- /dev/null +++ b/app/src/routes/(app)/import-export/+page.svelte @@ -0,0 +1,432 @@ + + +Laden…
+{:else} + + +✓ {exportStatus}
+ {/if} +Vollständige Sicherungskopie aller Vereinsdaten als JSON – für Archivierung oder Wechsel der Software (DSGVO Art. 20).
+ +CSV-Datei hochladen – die Spalten werden automatisch erkannt und können vor dem Import angepasst werden.
+ + {#if importPhase === 'idle'} + + + {:else if importPhase === 'mapping'} +Vor- und Nachname sind Pflichtfelder.
+ +✓ {importResult.ok} Mitglieder importiert
+ {#if importResult.fehler.length > 0} +{importResult.fehler.length} Probleme:
+