diff --git a/apps/mana/apps/web/src/lib/components/settings/searchIndex.ts b/apps/mana/apps/web/src/lib/components/settings/searchIndex.ts index 66403c913..f88f85244 100644 --- a/apps/mana/apps/web/src/lib/components/settings/searchIndex.ts +++ b/apps/mana/apps/web/src/lib/components/settings/searchIndex.ts @@ -42,9 +42,18 @@ export const categories: Category[] = [ { id: 'data', label: 'Daten & Sync', - description: 'Cloud-Sync, Export & DSGVO', + description: 'Cloud-Sync, Export, Backup & DSGVO', icon: Cloud, - anchors: ['cloud-sync', 'my-data'], + anchors: [ + 'cloud-sync', + 'my-data', + 'auth-data', + 'credits-data', + 'project-data', + 'retention', + 'backup', + 'danger-zone', + ], }, ]; @@ -139,7 +148,7 @@ export const searchIndex: SearchEntry[] = [ // Data { label: 'Cloud Sync', - keywords: ['sync', 'backup', 'geräte'], + keywords: ['sync', 'geräte'], category: 'data', anchor: 'cloud-sync', }, @@ -150,10 +159,40 @@ export const searchIndex: SearchEntry[] = [ anchor: 'my-data', }, { - label: 'Konto löschen', - keywords: ['delete', 'gdpr', 'dsgvo'], + label: 'Authentifizierung', + keywords: ['sessions', '2fa', 'login'], category: 'data', - anchor: 'my-data', + anchor: 'auth-data', + }, + { + label: 'Credits & Transaktionen', + keywords: ['guthaben', 'transaktionen'], + category: 'data', + anchor: 'credits-data', + }, + { + label: 'Projektdaten', + keywords: ['projekte', 'apps', 'statistik'], + category: 'data', + anchor: 'project-data', + }, + { + label: 'Aufbewahrungsfristen', + keywords: ['retention', 'dsgvo', 'fristen'], + category: 'data', + anchor: 'retention', + }, + { + label: 'Backup & Wiederherstellung', + keywords: ['backup', 'restore', 'import', 'archiv', '.mana'], + category: 'data', + anchor: 'backup', + }, + { + label: 'Konto löschen', + keywords: ['delete', 'gdpr', 'dsgvo', 'gefahrenzone'], + category: 'data', + anchor: 'danger-zone', }, ]; diff --git a/apps/mana/apps/web/src/lib/components/settings/sections/DataSection.svelte b/apps/mana/apps/web/src/lib/components/settings/sections/DataSection.svelte index 7991a397a..4eabf3847 100644 --- a/apps/mana/apps/web/src/lib/components/settings/sections/DataSection.svelte +++ b/apps/mana/apps/web/src/lib/components/settings/sections/DataSection.svelte @@ -1,27 +1,7 @@ - - - - - - - - - + + diff --git a/apps/mana/apps/web/src/lib/components/settings/sections/MyDataSection.svelte b/apps/mana/apps/web/src/lib/components/settings/sections/MyDataSection.svelte index 2b8a906dd..23b1db293 100644 --- a/apps/mana/apps/web/src/lib/components/settings/sections/MyDataSection.svelte +++ b/apps/mana/apps/web/src/lib/components/settings/sections/MyDataSection.svelte @@ -1,20 +1,22 @@ -
- -
-
-

Meine Daten

-

- Übersicht über alle deine gespeicherten Daten (GDPR/DSGVO) -

-
- {#if userData} -
- - -
- {/if} -
- - -
+ + -
- -
-

- Hier siehst du alle Daten, die wir uber dich speichern. Mehr Informationen findest du in - unserer - +

-
-
+ + QR + + +
+ {/if} + {/snippet} + {#if loading} -
- {#each Array(4) as _} -
-
-
-
- {/each} -
+
{:else if error} -
-

{error}

- +
+

{error}

+
{:else if userData} - - -
-
-
- - {(userData.user.name || userData.user.email)[0].toUpperCase()} +
+
+
+ {(userData.user.name || userData.user.email)[0].toUpperCase()} +
+
+

{userData.user.name || 'Kein Name'}

+

{userData.user.email}

+
+
+ {userData.user.role} + {#if userData.user.emailVerified} + + + verifiziert + + {:else} + + + nicht verifiziert -
-
-

{userData.user.name || 'Kein Name'}

-

{userData.user.email}

-
- - {userData.user.role} - - {#if userData.user.emailVerified} - - - Email verifiziert - - {:else} - - - Email nicht verifiziert - - {/if} -
-

- Registriert am {formatDate(userData.user.createdAt)} -

-
-
-
- - - -
- - - - -
- - -
- - -
-

- - Authentifizierung -

-
-
- Aktive Sessions - {userData.auth.sessionsCount} -
-
- Verknupfte Accounts - {userData.auth.accountsCount} -
-
- 2FA aktiviert - - {userData.auth.has2FA ? 'Ja' : 'Nein'} - -
-
- Letzter Login - - {userData.auth.lastLoginAt ? formatDate(userData.auth.lastLoginAt) : '-'} - -
-
-
-
- - - -
-

- - Credits -

-
-
- Aktueller Stand - {userData.credits.balance} -
-
- Gesamt verdient - +{userData.credits.totalEarned} -
-
- Gesamt ausgegeben - -{userData.credits.totalSpent} -
-
- Transaktionen - {userData.credits.transactionsCount} -
-
-
-
-
- - -
-

Projektdaten

-
- {#each userData.projects as project} - - {/each} -
-
- - - -
-

- - Aufbewahrungsfristen -

-

So lange speichern wir deine Daten:

-
-
- Benutzerkonto & Profil - Bis zur Loschung -
-
- Sessions & Login-Historie - 90 Tage nach Ablauf -
-
- Credit-Transaktionen - 10 Jahre (gesetzlich) -
-
- Security-Logs - 1 Jahr -
-
- Projektdaten (Chat, Todo, etc.) - Bis zur Loschung -
-
-
-
- - - -
-

- - Backup & Wiederherstellung -

-

- Lade eine vollstandige Kopie deiner synchronisierten Daten als .mana-Archiv - (ZIP) herunter. Enthalt den kompletten Sync-Event-Stream plus Manifest mit - Integritats-Hash — geeignet fur Account-Migration, Backups oder DSGVO-Datenportabilitat. - Sensible Felder bleiben dabei verschlusselt. -

-
- - - Experimentell — Import folgt in Kurze. - -
- {#if backupError} -

{backupError}

- {/if} - - -
-

Backup einspielen

-

- Wahle eine .mana-Datei aus. Die enthaltenen Events werden in deine lokale - Datenbank gespielt — nur Backups deines eigenen Accounts werden akzeptiert. -

-
- - -
- - {#if importProgress} -
-

{importProgressLabel(importProgress)}

- {#if importProgress.total > 0} -
-
-
- {/if} -
- {/if} - - {#if importResult} -
-

- - {importResult.appliedEvents} Events aus Backup vom - {formatDate(importResult.manifest.createdAt)} eingespielt ({importResult.manifest - .apps.length} Apps). -

-
- {/if} - - {#if importError} -

{importError}

{/if}
-
- - -
-
-
- -
-
-

Gefahrenzone

-

Diese Aktionen sind unwiderruflich

-
-
- -
-
-
-

Alle meine Daten loschen

-

- Loscht dein Konto und alle damit verbundenen Daten dauerhaft aus allen Projekten. - Diese Aktion kann nicht ruckgangig gemacht werden. -

-
- -
+
+
+

Registriert am

+ {formatDate(userData.user.createdAt)}
- + +
+
+

Gesamt-Entitäten

+

Datensätze über alle Apps hinweg

+
+ {formatNum(userData.totals.totalEntities)} +
+ +
+
+

Projekte mit Daten

+
+ + {userData.totals.projectsWithData} / {userData.projects.length} + +
+
+ +

+ Keine Tracking-Cookies — anonyme Analyse via Umami. Details in der + Datenschutzerklärung. +

{/if} -
+ + +{#if userData} + + + +
+
+

Aktive Sessions

+ {userData.auth.sessionsCount} +
+
+

Verknüpfte Accounts

+ {userData.auth.accountsCount} +
+
+

Zwei-Faktor (2FA)

+ + {userData.auth.has2FA ? 'Aktiviert' : 'Deaktiviert'} + +
+
+

Letzter Login

+ + {userData.auth.lastLoginAt ? formatDate(userData.auth.lastLoginAt) : '—'} + +
+
+
+ + + + +
+
+

Aktueller Stand

+ {formatNum(userData.credits.balance)} +
+
+

Gesamt verdient

+ +{formatNum(userData.credits.totalEarned)} +
+
+

Gesamt ausgegeben

+ −{formatNum(userData.credits.totalSpent)} +
+
+

Transaktionen

+ {userData.credits.transactionsCount} +
+
+
+ + + + + + + + + + + + + + {#each userData.projects as project (project.projectId)} + {@const AppIcon = getApp(project.projectId)?.icon} + + + + + + {/each} + +
AppEinträgeLetzte Aktivität
+
+ 0} + class:empty={project.available && project.totalCount === 0} + class:error={!project.available} + title={project.available + ? project.totalCount > 0 + ? 'Aktiv' + : 'Keine Daten' + : project.error || 'Nicht verfügbar'} + > + + {#if AppIcon} + + {:else} + {project.icon} + {/if} + + {project.projectName} +
+
+ {#if project.available} + {formatNum(project.totalCount)} + {:else} + + {/if} + + {#if project.available} + {formatRelativeTime(project.lastActivityAt)} + {:else} + {project.error || 'nicht erreichbar'} + {/if} +
+
+ + + + +
+
+

Benutzerkonto & Profil

+ Bis zur Löschung +
+
+

Sessions & Login-Historie

+ 90 Tage nach Ablauf +
+
+

Credit-Transaktionen

+ 10 Jahre (gesetzlich) +
+
+

Security-Logs

+ 1 Jahr +
+
+

Projektdaten (Chat, Todo, …)

+ Bis zur Löschung +
+
+
+ + + + +
+
+
+

Backup herunterladen

+

+ ZIP mit Event-Stream + Integritäts-Hash. Sensible Felder bleiben verschlüsselt. +

+
+ +
+
+
+

Backup einspielen

+

Nur Backups deines eigenen Accounts werden akzeptiert.

+
+ +
+
+ + + + {#if backupError} +

{backupError}

+ {/if} + + {#if importProgress} +
+

{importProgressLabel(importProgress)}

+ {#if importProgress.total > 0} +
+
+
+ {/if} +
+ {/if} + + {#if importResult} +

+ + {importResult.appliedEvents} Events aus Backup vom {formatDate( + importResult.manifest.createdAt + )} eingespielt ({importResult.manifest.apps.length} Apps). +

+ {/if} + + {#if importError} +

{importError}

+ {/if} +
+ + + + +
+
+
+

Alle meine Daten löschen

+

+ Löscht dein Konto und alle verbundenen Daten dauerhaft aus allen Projekten. Kann nicht + rückgängig gemacht werden. +

+
+ +
+
+
+{/if} - - (showQRDialog = false)} /> + + diff --git a/apps/mana/apps/web/src/lib/components/settings/sections/SyncSection.svelte b/apps/mana/apps/web/src/lib/components/settings/sections/SyncSection.svelte index a46d889b2..7e4709d37 100644 --- a/apps/mana/apps/web/src/lib/components/settings/sections/SyncSection.svelte +++ b/apps/mana/apps/web/src/lib/components/settings/sections/SyncSection.svelte @@ -1,10 +1,12 @@ -
+ + + {#if syncBilling.loading} -
-
+
+
{:else} -
- - -
-

Status

- -
-
- {syncBilling.active ? '🔄' : syncBilling.paused ? '⏸️' : '☁️'} -
-
-

- {#if syncBilling.active} - Aktiv - {:else if syncBilling.paused} - Pausiert - {:else} - Inaktiv - {/if} -

- {#if syncBilling.active && syncBilling.nextChargeAt} -

- Nächste Abbuchung: {formatDate(syncBilling.nextChargeAt)} -

- {:else if syncBilling.paused} -

- Credits reichen nicht aus — lade Credits auf um fortzufahren -

- {:else} -

- Deine Daten sind nur lokal auf diesem Gerät gespeichert -

- {/if} -
-
- - {#if balance} -
-
- Verfügbare Credits - {formatCredits(balance.balance)} -
-
- {/if} - - {#if error} -
-

{error}

-
- {/if} - - {#if syncBilling.active} - - {:else} - - {#if balance !== null && balance.balance < SYNC_PRICES[selectedInterval]} -

- Nicht genügend Credits. - Aufladen -

+
+
+
+

Status

+

+ {#if syncBilling.active && syncBilling.nextChargeAt} + Nächste Abbuchung am {formatDate(syncBilling.nextChargeAt)} + {:else if syncBilling.active} + Synchronisiert verschlüsselt über alle Geräte + {:else if syncBilling.paused} + Credits reichen nicht aus — lade Credits auf um fortzufahren + {:else} + Deine Daten sind nur lokal auf diesem Gerät gespeichert {/if} - {/if} +

- + + {#if syncBilling.active} + + Aktiv + {:else if syncBilling.paused} + + Pausiert + {:else} + + Inaktiv + {/if} + +
- - -
-

Abrechnungsintervall

- -
- {#each ['monthly', 'quarterly', 'yearly'] as const as iv} - - {/each} + {#if balance} +
+
+

Verfügbare Credits

+

+ Credits aufladen +

+ {formatCredits(balance.balance)} +
+ {/if} - {#if syncBilling.active && selectedInterval !== syncBilling.interval} +
+
+

Abrechnungsintervall

+

+ {SYNC_PRICES[selectedInterval]} Credits · {INTERVAL_HINTS[selectedInterval]} +

+
+
+ {#each ['monthly', 'quarterly', 'yearly'] as const as iv} -

- Änderung gilt ab der nächsten Abbuchung -

- {/if} - -
-

- Cloud Sync synchronisiert deine Daten verschlüsselt über alle Geräte. Deine lokalen - Daten bleiben immer erhalten — auch wenn Sync pausiert oder deaktiviert wird. -

-
+ {/each}
- +
+ + {#if error} +

{error}

+ {/if} + +
+ {#if syncBilling.active} + {#if intervalChanged} + +

Änderung gilt ab der nächsten Abbuchung

+ {/if} + + {:else} + + {#if insufficientCredits} +

+ Nicht genügend Credits. Aufladen +

+ {/if} + {/if} +
+ +

+ Cloud Sync synchronisiert deine Daten verschlüsselt über alle Geräte. Lokale Daten bleiben + immer erhalten — auch wenn Sync pausiert oder deaktiviert wird. +

{/if} -
+ + +