managarten/memoro/apps/web/src/lib/components/statistics/EngagementCard.svelte
Till-JS ef70a1af0b Commit Message feat: implement comprehensive shared packages architecture for monorepo SUMMARY: Introduce 10 shared packages to unify common code across all 4 web apps, reducing ~3,000 lines of duplicated code and establishing consistent patterns for authentication, UI components, theming, and utilities. NEW SHARED PACKAGES: - @manacore/shared-auth: Unified auth logic (token management, JWT utils, fetch interceptor, storage/device/network adapters) - @manacore/shared-auth-ui: Reusable auth UI (LoginPage, RegisterPage, OAuth buttons for Google/Apple) - @manacore/shared-tailwind: Unified Tailwind config with 4 themes (lume, nature, stone, ocean) and light/dark mode support - @manacore/shared-icons: Phosphor-based icon library (40+ icons) - @manacore/shared-ui: Atomic design system (Text, Button, Badge, Toggle, Input, Modal) - @manacore/shared-i18n: Unified i18n setup with locale detection - @manacore/shared-config: Environment validation with Zod - @manacore/shared-subscriptio n-types: Subscription type definitions - @manacore/shared-subscriptio n-ui: Subscription UI components (planned) EXTENDED PACKAGES: - @manacore/shared-types: Added auth.ts, theme.ts, ui.ts, common.ts - @manacore/shared-utils: Added format.ts, validation.ts APP MIGRATIONS: - memoro/web: Migrated login (549→46 LOC), tailwind (165→12 LOC), removed 15+ duplicate components - manacore/web: Migrated to client-side auth with shared-auth, added new components (Icon, ThemeToggle, Logo) - manadeck/web: Replaced local authService/tokenManager with shared-auth, migrated auth pages - maerchenzauber/web: Added auth setup, stores, components, routes DELETED FILES (migrated to shared packages): - OAuth buttons (Google/Apple) from memoro, manacore, manadeck - Local authService, tokenManager, deviceManager, jwt utils - Duplicate Modal, Toggle, Text components - iconPaths and ManaIcon components - Subscription-related components (CostCard, PackageCard, etc.) BENEFITS: - 92% reduction in login page code - 93% reduction in tailwind config code - Consistent theming across all apps - Single source of truth for auth logic - Easier maintenance and updates BREAKING CHANGES: - Icon imports now from @manacore/shared-icons - Modal imports from @manacore/shared-ui - OAuth config via setGoogleCl ientId()/setAppleConfig()
2025-11-24 21:09:20 +01:00

80 lines
2.1 KiB
Svelte

<script lang="ts">
import GlassCard from './GlassCard.svelte';
import StatRow from './StatRow.svelte';
import { Text } from '@manacore/shared-ui';
interface Props {
mostViewedMemo: { id: string; title: string; viewCount: number } | null;
lastViewedMemo: { id: string; title: string; lastViewed: string } | null;
unreadMemos: number;
memoCount: number;
}
let { mostViewedMemo, lastViewedMemo, unreadMemos, memoCount }: Props = $props();
const readMemos = memoCount - unreadMemos;
const readPercentage = memoCount > 0 ? Math.round((readMemos / memoCount) * 100) : 0;
</script>
<GlassCard>
{#snippet children()}
<div>
<Text variant="large" weight="bold" class="mb-5 text-2xl">Engagement</Text>
<!-- View Statistics -->
<Text variant="muted" weight="semibold" class="mb-2 uppercase tracking-wide">
Aufrufe
</Text>
<div class="mb-4 -space-y-px">
{#if mostViewedMemo}
<StatRow
title="Meist angesehen"
value={`${mostViewedMemo.viewCount}x`}
subtitle={mostViewedMemo.title}
icon="eye-outline"
/>
{/if}
{#if lastViewedMemo}
<StatRow
title="Zuletzt angesehen"
value={new Date(lastViewedMemo.lastViewed).toLocaleDateString('de-DE')}
subtitle={lastViewedMemo.title}
icon="time-outline"
/>
{/if}
</div>
<!-- Reading Statistics -->
<Text variant="muted" weight="semibold" class="mb-2 uppercase tracking-wide">
Lesestatus
</Text>
<div class="-space-y-px">
<StatRow
title="Ungelesene Memos"
value={unreadMemos.toString()}
icon="mail-unread-outline"
/>
<StatRow
title="Gelesene Memos"
value={readMemos.toString()}
icon="checkmark-done-outline"
/>
<StatRow
title="Gelesen"
value={`${readPercentage}%`}
subtitle={`${readMemos} von ${memoCount} Memos`}
icon="stats-chart-outline"
/>
</div>
{#if unreadMemos > 0}
<div class="mt-4 rounded-xl bg-menu/30 p-3">
<Text variant="small" class="text-theme-secondary">
💡 Du hast noch {unreadMemos}
{unreadMemos === 1 ? 'ungelesenes Memo' : 'ungelesene Memos'}
</Text>
</div>
{/if}
</div>
{/snippet}
</GlassCard>