diff --git a/apps/citycorners/apps/backend/src/db/seed.ts b/apps/citycorners/apps/backend/src/db/seed.ts index 4cbbcf13e..2abb30ead 100644 --- a/apps/citycorners/apps/backend/src/db/seed.ts +++ b/apps/citycorners/apps/backend/src/db/seed.ts @@ -23,7 +23,7 @@ async function seed() { address: 'Münsterplatz 1, 78462 Konstanz', latitude: 47.6603, longitude: 9.1757, - imageUrl: '/images/muenster.svg', + imageUrl: '/images/muenster.jpg', timeline: [ { year: '615', event: 'Grundsteinlegung' }, { year: '1089', event: 'Romanischer Neubau' }, @@ -38,7 +38,7 @@ async function seed() { address: 'Hafenstraße, 78462 Konstanz', latitude: 47.6596, longitude: 9.1784, - imageUrl: '/images/imperia.svg', + imageUrl: '/images/imperia.jpg', timeline: [{ year: '1993', event: 'Aufstellung im Hafen' }], }, { @@ -49,7 +49,7 @@ async function seed() { address: 'Seestraße 25, 78464 Konstanz', latitude: 47.6589, longitude: 9.1795, - imageUrl: '/images/ophelia.svg', + imageUrl: '/images/ophelia.jpg', }, { name: 'LAGO Shopping Center', @@ -58,7 +58,7 @@ async function seed() { address: 'Bodanstraße 1, 78462 Konstanz', latitude: 47.6615, longitude: 9.1742, - imageUrl: '/images/lago.svg', + imageUrl: '/images/lago.jpg', }, { name: 'Rosgartenmuseum', diff --git a/apps/citycorners/apps/landing/public/images/alm.jpg b/apps/citycorners/apps/landing/public/images/alm.jpg new file mode 100644 index 000000000..d573e3fb2 Binary files /dev/null and b/apps/citycorners/apps/landing/public/images/alm.jpg differ diff --git a/apps/citycorners/apps/landing/public/images/alm.svg b/apps/citycorners/apps/landing/public/images/alm.svg deleted file mode 100644 index 9b5db9e6e..000000000 --- a/apps/citycorners/apps/landing/public/images/alm.svg +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - ARCHÄOLOGIE - - Archäologisches Landesmuseum - diff --git a/apps/citycorners/apps/landing/public/images/imperia.jpg b/apps/citycorners/apps/landing/public/images/imperia.jpg new file mode 100644 index 000000000..e9115853a Binary files /dev/null and b/apps/citycorners/apps/landing/public/images/imperia.jpg differ diff --git a/apps/citycorners/apps/landing/public/images/imperia.svg b/apps/citycorners/apps/landing/public/images/imperia.svg deleted file mode 100644 index 682906370..000000000 --- a/apps/citycorners/apps/landing/public/images/imperia.svg +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Imperia - diff --git a/apps/citycorners/apps/landing/public/images/lago.jpg b/apps/citycorners/apps/landing/public/images/lago.jpg new file mode 100644 index 000000000..e2368783f Binary files /dev/null and b/apps/citycorners/apps/landing/public/images/lago.jpg differ diff --git a/apps/citycorners/apps/landing/public/images/lago.svg b/apps/citycorners/apps/landing/public/images/lago.svg deleted file mode 100644 index eb3f0a4e6..000000000 --- a/apps/citycorners/apps/landing/public/images/lago.svg +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - LAGO - - - - - - - LAGO Shopping-Center - diff --git a/apps/citycorners/apps/landing/public/images/muenster.jpg b/apps/citycorners/apps/landing/public/images/muenster.jpg new file mode 100644 index 000000000..803258af0 Binary files /dev/null and b/apps/citycorners/apps/landing/public/images/muenster.jpg differ diff --git a/apps/citycorners/apps/landing/public/images/muenster.svg b/apps/citycorners/apps/landing/public/images/muenster.svg deleted file mode 100644 index 645514adf..000000000 --- a/apps/citycorners/apps/landing/public/images/muenster.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Konstanzer Münster - diff --git a/apps/citycorners/apps/landing/public/images/ophelia.jpg b/apps/citycorners/apps/landing/public/images/ophelia.jpg new file mode 100644 index 000000000..79190ba20 Binary files /dev/null and b/apps/citycorners/apps/landing/public/images/ophelia.jpg differ diff --git a/apps/citycorners/apps/landing/public/images/ophelia.svg b/apps/citycorners/apps/landing/public/images/ophelia.svg deleted file mode 100644 index ab557b46e..000000000 --- a/apps/citycorners/apps/landing/public/images/ophelia.svg +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ★★ - - Restaurant Ophelia - diff --git a/apps/citycorners/apps/landing/public/images/rosgartenmuseum.jpg b/apps/citycorners/apps/landing/public/images/rosgartenmuseum.jpg new file mode 100644 index 000000000..0113dfa81 Binary files /dev/null and b/apps/citycorners/apps/landing/public/images/rosgartenmuseum.jpg differ diff --git a/apps/citycorners/apps/landing/public/images/rosgartenmuseum.svg b/apps/citycorners/apps/landing/public/images/rosgartenmuseum.svg deleted file mode 100644 index b2619193d..000000000 --- a/apps/citycorners/apps/landing/public/images/rosgartenmuseum.svg +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - ROSGARTENMUSEUM - - Rosgartenmuseum - diff --git a/apps/citycorners/apps/landing/src/data/locations.json b/apps/citycorners/apps/landing/src/data/locations.json index 62ebe85c4..f75a9167d 100644 --- a/apps/citycorners/apps/landing/src/data/locations.json +++ b/apps/citycorners/apps/landing/src/data/locations.json @@ -4,7 +4,7 @@ "name": "Konstanzer Münster", "category": "Sehenswürdigkeit", "description": "Das Konstanzer Münster ist eine imposante Basilika, die über Jahrhunderte das Zentrum des Bistums Konstanz war. Besucher können den Turm besteigen und einen atemberaubenden Blick über die Stadt und den Bodensee genießen.", - "image": "/images/muenster.svg", + "image": "/images/muenster.jpg", "address": "Münsterplatz 1, 78462 Konstanz", "coordinates": { "lat": 47.663, @@ -28,7 +28,7 @@ "name": "Imperia", "category": "Sehenswürdigkeit", "description": "Die Imperia ist eine satirische Statue im Hafen von Konstanz, die an das Konzil von Konstanz erinnert. Sie dreht sich langsam um ihre Achse und ist ein beliebtes Fotomotiv.", - "image": "/images/imperia.svg", + "image": "/images/imperia.jpg", "address": "Hafenstraße, 78462 Konstanz", "coordinates": { "lat": 47.66, @@ -40,7 +40,7 @@ "name": "Restaurant Ophelia", "category": "Restaurant", "description": "Das mit zwei Michelin-Sternen ausgezeichnete Restaurant Ophelia bietet eine exquisite Küche in einem eleganten Ambiente. Es befindet sich im Hotel Riva am Ufer des Bodensees.", - "image": "/images/ophelia.svg", + "image": "/images/ophelia.jpg", "address": "Seestraße 25, 78464 Konstanz", "coordinates": { "lat": 47.67, @@ -52,7 +52,7 @@ "name": "LAGO Shopping-Center", "category": "Laden", "description": "Das LAGO ist das größte Einkaufszentrum am Bodensee und bietet eine Vielzahl von Geschäften, Restaurants und Cafés. Es ist ein beliebter Treffpunkt für Einheimische und Touristen.", - "image": "/images/lago.svg", + "image": "/images/lago.jpg", "address": "Bodanstraße 1, 78462 Konstanz", "coordinates": { "lat": 47.658, @@ -64,7 +64,7 @@ "name": "Rosgartenmuseum", "category": "Museum", "description": "Das Rosgartenmuseum ist das städtische Museum für Kunst, Kultur und Geschichte von Konstanz und der Bodenseeregion. Es wurde 1870 gegründet und befindet sich in einem ehemaligen Zunfthaus.", - "image": "/images/rosgartenmuseum.svg", + "image": "/images/rosgartenmuseum.jpg", "address": "Rosgartenstraße 3-5, 78462 Konstanz", "coordinates": { "lat": 47.661, @@ -83,7 +83,7 @@ "name": "Archäologisches Landesmuseum Baden-Württemberg", "category": "Museum", "description": "Das Archäologische Landesmuseum (ALM) in Konstanz ist ein Zweigmuseum des ALM in Stuttgart und zeigt Funde aus der Archäologie, Geschichte und Kultur der Region.", - "image": "/images/alm.svg", + "image": "/images/alm.jpg", "address": "Benediktinerplatz 5, 78467 Konstanz", "coordinates": { "lat": 47.665, diff --git a/apps/manacore/apps/web/package.json b/apps/manacore/apps/web/package.json index 6b25c01cd..f838b375e 100644 --- a/apps/manacore/apps/web/package.json +++ b/apps/manacore/apps/web/package.json @@ -42,8 +42,8 @@ "vitest": "^4.0.14" }, "dependencies": { + "@manacore/credit-operations": "workspace:^", "@manacore/qr-export": "workspace:*", - "@manacore/wallpaper-generator": "workspace:*", "@manacore/shared-auth": "workspace:*", "@manacore/shared-auth-ui": "workspace:*", "@manacore/shared-branding": "workspace:*", @@ -63,6 +63,7 @@ "@manacore/shared-types": "workspace:*", "@manacore/shared-ui": "workspace:*", "@manacore/shared-utils": "workspace:*", + "@manacore/wallpaper-generator": "workspace:*", "svelte-dnd-action": "^0.9.68", "svelte-i18n": "^4.0.0" }, diff --git a/apps/manacore/apps/web/src/routes/(app)/credits/+page.svelte b/apps/manacore/apps/web/src/routes/(app)/credits/+page.svelte index 5fc11853f..9b0caf649 100644 --- a/apps/manacore/apps/web/src/routes/(app)/credits/+page.svelte +++ b/apps/manacore/apps/web/src/routes/(app)/credits/+page.svelte @@ -8,13 +8,91 @@ type CreditTransaction, type CreditPackage, } from '$lib/api/credits'; + import { + OPERATION_METADATA, + CREDIT_COSTS, + CreditCategory, + formatCreditCost, + type CreditOperationType, + } from '@manacore/credit-operations'; let balance = $state(null); let transactions = $state([]); let packages = $state([]); let loading = $state(true); let error = $state(null); - let activeTab = $state<'overview' | 'transactions' | 'packages'>('overview'); + let activeTab = $state<'overview' | 'transactions' | 'packages' | 'costs'>('overview'); + let costFilter = $state<'all' | 'ai' | 'productivity' | 'premium'>('all'); + + // Build pricing data grouped by app + const allOperations = $derived( + Object.entries(OPERATION_METADATA).map(([op, meta]) => ({ + operation: op as CreditOperationType, + name: meta.name, + description: meta.description, + category: meta.category, + app: meta.app, + cost: CREDIT_COSTS[op as CreditOperationType], + formattedCost: formatCreditCost(CREDIT_COSTS[op as CreditOperationType]), + })) + ); + + const filteredOperations = $derived( + costFilter === 'all' + ? allOperations + : allOperations.filter((op) => { + if (costFilter === 'ai') return op.category === CreditCategory.AI; + if (costFilter === 'productivity') return op.category === CreditCategory.PRODUCTIVITY; + if (costFilter === 'premium') return op.category === CreditCategory.PREMIUM; + return true; + }) + ); + + const operationsByApp = $derived(() => { + const groups: Record = {}; + for (const op of filteredOperations) { + if (!groups[op.app]) groups[op.app] = []; + groups[op.app].push(op); + } + // Sort apps alphabetically + return Object.fromEntries(Object.entries(groups).sort(([a], [b]) => a.localeCompare(b))); + }); + + const APP_LABELS: Record = { + calendar: 'Kalender', + chat: 'Chat', + contacts: 'Kontakte', + context: 'Context', + general: 'Allgemein', + manadeck: 'ManaDeck', + matrix: 'Matrix Bots', + nutriphi: 'NutriPhi', + picture: 'Picture', + planta: 'Planta', + presi: 'Presi', + questions: 'Questions', + skilltree: 'SkillTree', + todo: 'Todo', + traces: 'Traces', + zitare: 'Zitare', + }; + + function getAppLabel(app: string): string { + return APP_LABELS[app] ?? app.charAt(0).toUpperCase() + app.slice(1); + } + + function getCategoryLabel(category: CreditCategory): string { + switch (category) { + case CreditCategory.AI: + return 'KI-Features'; + case CreditCategory.PRODUCTIVITY: + return 'Erstellen'; + case CreditCategory.PREMIUM: + return 'Premium'; + default: + return category; + } + } let processingPackageId = $state(null); // Toast notification @@ -26,6 +104,7 @@ const tab = $page.url.searchParams.get('tab'); if (tab === 'packages') activeTab = 'packages'; else if (tab === 'transactions') activeTab = 'transactions'; + else if (tab === 'costs') activeTab = 'costs'; // Handle success/canceled from Stripe redirect const success = $page.url.searchParams.get('success'); @@ -212,6 +291,14 @@ > Credits kaufen + @@ -394,6 +481,75 @@

{/if} + {:else if activeTab === 'costs'} + +
+ {#each [{ key: 'all', label: 'Alle' }, { key: 'ai', label: 'KI-Features' }, { key: 'productivity', label: 'Erstellen' }, { key: 'premium', label: 'Premium' }] as filter} + + {/each} +
+ + +
+

+ Lesen, Bearbeiten, Löschen und Organisieren von Einträgen ist immer kostenlos. Credits werden nur für die unten aufgeführten Aktionen verbraucht. +

+
+ + + {@const groups = operationsByApp()} +
+ {#each Object.entries(groups) as [app, operations]} + +

{getAppLabel(app)}

+
+ {#each operations as op} +
+
+

{op.name}

+

{op.description}

+
+
+ {getCategoryLabel(op.category)} + + {op.cost === 0 ? 'Kostenlos' : op.formattedCost} + +
+
+ {/each} +
+
+ {/each} + + {#if Object.keys(groups).length === 0} + +

+ Keine Operationen in dieser Kategorie. +

+
+ {/if} +
{/if} {/if} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 15177e6c5..35da066a3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2174,6 +2174,9 @@ importers: apps/manacore/apps/web: dependencies: + '@manacore/credit-operations': + specifier: workspace:^ + version: link:../../../../packages/credit-operations '@manacore/qr-export': specifier: workspace:* version: link:../../../../packages/qr-export @@ -7289,6 +7292,34 @@ importers: specifier: ^3.0.5 version: 3.2.4(@types/debug@4.1.12)(@types/node@24.10.1)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(jiti@2.6.1)(jsdom@27.2.0)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.1) + services/it-landing: + dependencies: + '@astrojs/check': + specifier: ^0.9.0 + version: 0.9.5(prettier-plugin-astro@0.14.1)(prettier@3.6.2)(typescript@5.9.3) + '@astrojs/sitemap': + specifier: ^3.2.1 + version: 3.6.0 + '@manacore/shared-landing-ui': + specifier: workspace:* + version: link:../../packages/shared-landing-ui + astro: + specifier: ^5.16.0 + version: 5.18.1(@netlify/blobs@10.4.1)(@types/node@24.10.1)(ioredis@5.9.2)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.53.3)(terser@5.44.1)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.1) + typescript: + specifier: ^5.0.0 + version: 5.9.3 + devDependencies: + '@astrojs/tailwind': + specifier: ^6.0.0 + version: 6.0.2(astro@5.18.1(@netlify/blobs@10.4.1)(@types/node@24.10.1)(ioredis@5.9.2)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.53.3)(terser@5.44.1)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.1))(tailwindcss@3.4.18(tsx@4.21.0)(yaml@2.8.1))(ts-node@10.9.2(@types/node@24.10.1)(typescript@5.9.3)) + '@tailwindcss/typography': + specifier: ^0.5.16 + version: 0.5.19(tailwindcss@3.4.18(tsx@4.21.0)(yaml@2.8.1)) + tailwindcss: + specifier: ^3.4.17 + version: 3.4.18(tsx@4.21.0)(yaml@2.8.1) + services/mana-api-gateway: dependencies: '@manacore/shared-nestjs-auth':