diff --git a/apps/manacore/apps/landing/src/content/manascore/about.md b/apps/manacore/apps/landing/src/content/manascore/about.md index 5f31eedd0..4dc0f5458 100644 --- a/apps/manacore/apps/landing/src/content/manascore/about.md +++ b/apps/manacore/apps/landing/src/content/manascore/about.md @@ -145,17 +145,18 @@ Bewertet die Sicherheitsmaßnahmen. Bewertet die User Experience und Accessibility. -| Kriterium | Punkte | -| ---------------------------- | ------ | -| i18n (mindestens 5 Sprachen) | 0-20 | -| Responsive Design | 0-15 | -| Keyboard Navigation | 0-10 | -| Focus Trapping (Modals) | 0-10 | -| ARIA Labels/Roles | 0-10 | -| Toast/Feedback System | 0-10 | -| Loading/Skeleton States | 0-10 | -| Dark/Light Mode | 0-10 | -| Immersive Mode | 0-5 | +| Kriterium | Punkte | +| -------------------------------- | ------ | +| i18n (mindestens 5 Sprachen) | 0-15 | +| Responsive Design | 0-15 | +| Keyboard Navigation | 0-10 | +| Focus Trapping (Modals) | 0-10 | +| ARIA Labels/Roles | 0-10 | +| Toast/Feedback System | 0-10 | +| Loading/Skeleton States | 0-10 | +| Dark/Light Mode | 0-10 | +| Help-Seite (shared-help-ui) | 0-5 | +| Feedback-Seite (shared-feedback) | 0-5 | --- @@ -229,6 +230,8 @@ Misst wie konsequent eine App die shared Packages des Monorepos nutzt: | `shared-branding` | Core | App-Icons, Farben, URLs | | `shared-i18n` | Core | Internationalisierung (Sprach-Utilities) | | `shared-error-tracking` | Core | GlitchTip Error Tracking | +| `shared-help-ui` | Core | Hilfe-Seite mit FAQ, Features, Shortcuts | +| `shared-feedback-ui` | Core | Feedback-Seite für Nutzer-Rückmeldungen | | `shared-storage` | Optional | S3/MinIO Datei-Upload (nur wenn relevant) | | `shared-llm` | Optional | LLM-Integration (nur wenn AI-Features) | diff --git a/packages/shared-help-types/src/index.ts b/packages/shared-help-types/src/index.ts index b45ede049..849480e20 100644 --- a/packages/shared-help-types/src/index.ts +++ b/packages/shared-help-types/src/index.ts @@ -11,3 +11,9 @@ export * from './schemas.js'; // Search types export * from './search.js'; + +// Shared Mana FAQ content +export { getManaFAQs, getManaFeature } from './mana-faq.js'; + +// Shared Privacy FAQ content +export { getPrivacyFAQs, type PrivacyFAQOptions } from './privacy-faq.js'; diff --git a/packages/shared-help-types/src/mana-faq.ts b/packages/shared-help-types/src/mana-faq.ts new file mode 100644 index 000000000..2f5ab5529 --- /dev/null +++ b/packages/shared-help-types/src/mana-faq.ts @@ -0,0 +1,95 @@ +/** + * Shared Mana/Credits FAQ content + * Reusable across all apps that have a /mana subscription page + */ + +import type { FAQItem, FeatureItem } from './content.js'; + +/** + * Returns shared FAQ items explaining the Mana credit system. + * Apps can spread these into their help content's faq array. + * + * @example + * ```ts + * import { getManaFAQs } from '@manacore/shared-help-types'; + * + * export function getMyAppHelpContent(locale: string): HelpContent { + * return { + * faq: [ + * ...appSpecificFaqs, + * ...getManaFAQs(locale), + * ], + * ... + * }; + * } + * ``` + */ +export function getManaFAQs(locale: string): FAQItem[] { + const isDE = locale === 'de'; + + return [ + { + id: 'faq-mana-what', + question: isDE ? 'Was ist Mana?' : 'What is Mana?', + answer: isDE + ? '

Mana ist die universelle Währung im ManaCore-Ökosystem. Mit Mana bezahlst du für Premium-Funktionen wie KI-Generierungen, Cloud-Modelle und erweiterte Features — app-übergreifend mit einem einzigen Guthaben.

' + : '

Mana is the universal currency in the ManaCore ecosystem. With Mana you pay for premium features like AI generations, cloud models, and advanced features — across all apps with a single balance.

', + category: 'billing', + order: 90, + language: isDE ? 'de' : 'en', + featured: true, + tags: isDE + ? ['mana', 'credits', 'guthaben', 'währung'] + : ['mana', 'credits', 'balance', 'currency'], + }, + { + id: 'faq-mana-get', + question: isDE ? 'Wie bekomme ich Mana?' : 'How do I get Mana?', + answer: isDE + ? '

Es gibt drei Wege, Mana zu erhalten:

Abonnenten können außerdem Mana an andere Nutzer verschenken.

' + : '

There are three ways to get Mana:

Subscribers can also gift Mana to other users.

', + category: 'billing', + order: 91, + language: isDE ? 'de' : 'en', + tags: isDE + ? ['mana', 'kaufen', 'abo', 'kostenlos', 'stream', 'trank'] + : ['mana', 'buy', 'subscription', 'free', 'stream', 'potion'], + }, + { + id: 'faq-mana-use', + question: isDE ? 'Wofür wird Mana verwendet?' : 'What is Mana used for?', + answer: isDE + ? '

Mana wird für Premium-Funktionen innerhalb der ManaCore-Apps verwendet:

Basis-Funktionen wie Aufgaben, Kalender, Kontakte, Dateien und Chats mit lokalen Modellen sind immer kostenlos.

' + : '

Mana is used for premium features within ManaCore apps:

Core features like tasks, calendar, contacts, files, and chats with local models are always free.

', + category: 'billing', + order: 92, + language: isDE ? 'de' : 'en', + tags: isDE + ? ['mana', 'verbrauch', 'kosten', 'kostenlos'] + : ['mana', 'usage', 'costs', 'free'], + }, + ]; +} + +/** + * Returns a shared feature item for the Mana credit system. + */ +export function getManaFeature(locale: string): FeatureItem { + const isDE = locale === 'de'; + + return { + id: 'feature-mana', + title: isDE ? 'Mana-Credits' : 'Mana Credits', + description: isDE + ? 'Universelles Guthaben für Premium-Features in allen ManaCore-Apps — 150 Mana/Monat kostenlos.' + : 'Universal balance for premium features across all ManaCore apps — 150 Mana/month for free.', + icon: '✨', + category: 'core', + highlights: isDE + ? ['150 Mana/Monat kostenlos', 'App-übergreifend', 'Abos & Einmalkäufe', 'Mana verschenken'] + : ['150 Mana/month free', 'Cross-app', 'Subscriptions & one-time', 'Gift Mana'], + content: '', + order: 99, + language: isDE ? 'de' : 'en', + }; +} diff --git a/packages/shared-help-types/src/privacy-faq.ts b/packages/shared-help-types/src/privacy-faq.ts new file mode 100644 index 000000000..5185be55c --- /dev/null +++ b/packages/shared-help-types/src/privacy-faq.ts @@ -0,0 +1,109 @@ +/** + * Shared Privacy, Data Protection & Tech Independence FAQ content + * Reusable across all apps — covers GDPR, encryption, self-hosting, + * tech stack independence, data export, account deletion + */ + +import type { FAQItem } from './content.js'; + +export interface PrivacyFAQOptions { + /** + * What kind of data does the app handle? + * Used in the main privacy FAQ to make it specific. + * @example 'Aufgaben' / 'tasks', 'Dateien' / 'files', 'Chats' / 'chats' + */ + dataTypeDE: string; + dataTypeEN: string; + + /** + * Optional extra bullet points for the main privacy FAQ (app-specific). + * Each entry is a single `
  • ` string (without the `
  • ` tags). + * @example ['Lokale Modelle: Deine Daten verlassen nie unseren Server'] + */ + extraBulletsDE?: string[]; + extraBulletsEN?: string[]; +} + +/** + * Returns shared FAQ items covering privacy, data protection, and tech independence. + * The main privacy FAQ can be customized per app via options. + * + * @example + * ```ts + * import { getPrivacyFAQs } from '@manacore/shared-help-types'; + * + * const privacyFAQs = getPrivacyFAQs(locale, { + * dataTypeDE: 'Aufgaben', + * dataTypeEN: 'tasks', + * extraBulletsDE: ['Offline: Funktioniert auch ohne Internet'], + * extraBulletsEN: ['Offline: Works without internet'], + * }); + * ``` + */ +export function getPrivacyFAQs(locale: string, options: PrivacyFAQOptions): FAQItem[] { + const isDE = locale === 'de'; + + const extraDE = (options.extraBulletsDE || []).map((b) => `
  • ${b}
  • `).join(''); + const extraEN = (options.extraBulletsEN || []).map((b) => `
  • ${b}
  • `).join(''); + + return [ + { + id: 'faq-privacy', + question: isDE + ? `Wie werden meine ${options.dataTypeDE} geschützt?` + : `How are my ${options.dataTypeEN} protected?`, + answer: isDE + ? `

    Deine Daten sind sicher bei ManaCore:

    ` + : `

    Your data is secure with ManaCore:

    `, + category: 'privacy', + order: 95, + language: isDE ? 'de' : 'en', + featured: true, + tags: isDE + ? ['datenschutz', 'dsgvo', 'sicherheit', 'verschlüsselung'] + : ['privacy', 'gdpr', 'security', 'encryption'], + }, + { + id: 'faq-tech-independence', + question: isDE + ? 'Wie unabhängig ist ManaCore von großen Tech-Konzernen?' + : 'How independent is ManaCore from big tech companies?', + answer: isDE + ? '

    ManaCore ist bewusst technologisch unabhängig aufgebaut:

    Das Ziel: Ein digitales Zuhause, das dir gehört — nicht Big Tech.

    ' + : '

    ManaCore is deliberately built to be technologically independent:

    The goal: A digital home that belongs to you — not big tech.

    ', + category: 'privacy', + order: 96, + language: isDE ? 'de' : 'en', + featured: true, + tags: isDE + ? ['unabhängig', 'self-hosted', 'eigene-server', 'kein-google', 'kein-aws'] + : ['independent', 'self-hosted', 'own-servers', 'no-google', 'no-aws'], + }, + { + id: 'faq-data-export', + question: isDE ? 'Kann ich meine Daten exportieren?' : 'Can I export my data?', + answer: isDE + ? '

    Ja! Du hast jederzeit volle Kontrolle über deine Daten:

    ' + : '

    Yes! You have full control over your data at all times:

    ', + category: 'privacy', + order: 97, + language: isDE ? 'de' : 'en', + tags: isDE + ? ['export', 'daten', 'portabilität', 'dsgvo', 'offene-formate'] + : ['export', 'data', 'portability', 'gdpr', 'open-formats'], + }, + { + id: 'faq-account-deletion', + question: isDE ? 'Kann ich mein Konto löschen?' : 'Can I delete my account?', + answer: isDE + ? '

    Ja, jederzeit:

    Wir empfehlen, vorher einen Datenexport durchzuführen.

    ' + : '

    Yes, at any time:

    We recommend performing a data export beforehand.

    ', + category: 'privacy', + order: 98, + language: isDE ? 'de' : 'en', + tags: isDE + ? ['konto', 'löschen', 'daten', 'entfernen'] + : ['account', 'delete', 'data', 'remove'], + }, + ]; +} diff --git a/packages/shared-ui/src/navigation/PillDropdown.svelte b/packages/shared-ui/src/navigation/PillDropdown.svelte index d839470cb..6b9943f19 100644 --- a/packages/shared-ui/src/navigation/PillDropdown.svelte +++ b/packages/shared-ui/src/navigation/PillDropdown.svelte @@ -123,6 +123,8 @@ 'M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1', // App icons grid: 'M4 5a1 1 0 011-1h4a1 1 0 011 1v4a1 1 0 01-1 1H5a1 1 0 01-1-1V5zM14 5a1 1 0 011-1h4a1 1 0 011 1v4a1 1 0 01-1 1h-4a1 1 0 01-1-1V5zM4 15a1 1 0 011-1h4a1 1 0 011 1v4a1 1 0 01-1 1H5a1 1 0 01-1-1v-4zM14 15a1 1 0 011-1h4a1 1 0 011 1v4a1 1 0 01-1 1h-4a1 1 0 01-1-1v-4z', + // Help icon (question mark circle) + help: 'M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zm-1-7v2h2v-2h-2zm2-1.645A3.502 3.502 0 0012 6.5 3.501 3.501 0 008.645 9h2.012A1.5 1.5 0 0112 8.5c.828 0 1.5.672 1.5 1.5 0 .828-.672 1.5-1.5 1.5a1 1 0 00-1 1V14h2v-.645z', // Mana icon (water drop) mana: 'M12.3 1c.03.05 7.3 9.67 7.3 13.7 0 4.03-3.27 7.3-7.3 7.3S5 18.73 5 14.7C5 10.66 12.3 1 12.3 1zm0 6.4c-.02.03-3.65 4.83-3.65 6.84 0 2.02 1.64 3.65 3.65 3.65s3.65-1.64 3.65-3.65c0-2.01-3.62-6.81-3.65-6.84z', }; diff --git a/packages/shared-ui/src/navigation/PillNavigation.svelte b/packages/shared-ui/src/navigation/PillNavigation.svelte index d66c86942..cd54b9f00 100644 --- a/packages/shared-ui/src/navigation/PillNavigation.svelte +++ b/packages/shared-ui/src/navigation/PillNavigation.svelte @@ -282,6 +282,8 @@ themesHref?: string; /** Spiral page href (shown in user dropdown). Set to empty string to hide. */ spiralHref?: string; + /** Help page href (shown in user dropdown). Set to empty string to hide. */ + helpHref?: string; } let { @@ -327,6 +329,7 @@ feedbackHref = '/feedback', themesHref, spiralHref, + helpHref, }: Props = $props(); // Type guards for elements @@ -873,6 +876,19 @@ }, ] : []), + ...(helpHref + ? [ + { + id: 'help', + label: 'Hilfe', + icon: 'help', + onClick: () => { + window.location.href = helpHref; + }, + active: currentPath === helpHref, + }, + ] + : []), ...(showLanguageSwitcher && languageItems.length > 0 ? [ { id: 'language-divider', label: '', divider: true },