der tenant admin hat eine neue, mobil unterstützende UI, login redirect funktioniert, typescript fehler wurden bereinigt. Neue Blog Posts von ChatGPT eingebaut, übersetzt von Gemini 2.5

This commit is contained in:
Codex Agent
2025-11-05 19:27:10 +01:00
parent adb93b5f9d
commit c6ac04eb15
44 changed files with 1995 additions and 1949 deletions

View File

@@ -3,8 +3,11 @@ import { useSearchParams } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
import { Button } from '@/components/ui/button';
import { AdminLayout } from '../components/AdminLayout';
import { CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { TenantHeroCard, FrostedCard, FrostedSurface } from '../components/tenant';
import { TasksSection } from './TasksPage';
import { TaskCollectionsSection } from './TaskCollectionsPage';
import { EmotionsSection } from './EmotionsPage';
@@ -19,7 +22,7 @@ function ensureValidTab(value: string | null): EngagementTab {
return 'tasks';
}
export default function EngagementPage(): JSX.Element {
export default function EngagementPage() {
const { t } = useTranslation('management');
const { t: tc } = useTranslation('common');
const [searchParams, setSearchParams] = useSearchParams();
@@ -41,37 +44,91 @@ export default function EngagementPage(): JSX.Element {
);
const heading = tc('navigation.engagement');
const heroDescription = t('engagement.hero.description', {
defaultValue: 'Kuratiere Aufgaben, Moderationskollektionen und Emotionen als kreative Toolbox für jedes Event.'
});
const heroSupporting = [
t('engagement.hero.summary.tasks', { defaultValue: 'Plane Aufgaben, die Gäste motivieren von Upload-Regeln bis zu Story-Prompts.' }),
t('engagement.hero.summary.collections', { defaultValue: 'Sammle Vorlagen und kollektive Inhalte, um Events im Handumdrehen neu zu starten.' })
];
const heroPrimaryAction = (
<Button
size="sm"
className="rounded-full bg-gradient-to-r from-[#ff5f87] via-[#ec4899] to-[#6366f1] px-6 text-white shadow-md shadow-rose-400/30 transition hover:from-[#ff4470] hover:via-[#ec4899] hover:to-[#4f46e5]"
onClick={() => handleTabChange('tasks')}
>
{t('engagement.hero.actions.tasks', 'Zu Aufgaben wechseln')}
</Button>
);
const heroSecondaryAction = (
<Button
size="sm"
variant="outline"
className="rounded-full border-white/70 bg-white/80 px-6 text-slate-900 shadow-sm hover:bg-white"
onClick={() => handleTabChange('collections')}
>
{t('engagement.hero.actions.collections', 'Kollektionen ansehen')}
</Button>
);
const heroAside = (
<FrostedSurface className="space-y-4 border-white/20 p-5 text-slate-900 shadow-md shadow-rose-300/20 dark:border-slate-800/70 dark:bg-slate-950/80">
<div>
<p className="text-xs uppercase tracking-[0.3em] text-slate-500 dark:text-slate-400">{t('engagement.hero.activeTab', { defaultValue: 'Aktiver Bereich' })}</p>
<p className="mt-2 text-lg font-semibold text-slate-900 dark:text-slate-100">{t(`engagement.tabs.${activeTab}.title`, { defaultValue: tc(`navigation.${activeTab}`) })}</p>
</div>
<p className="text-xs text-slate-600 dark:text-slate-400">
{t('engagement.hero.tip', 'Wechsle Tabs, um Aufgaben, Kollektionen oder Emotionen zu bearbeiten und direkt in Events einzubinden.')}
</p>
</FrostedSurface>
);
return (
<AdminLayout
title={heading}
subtitle={t('engagement.subtitle', 'Bündle Aufgaben, Vorlagen und Emotionen für deine Events.')}
>
<Tabs value={activeTab} onValueChange={handleTabChange} className="space-y-6">
<TabsList className="grid w-full grid-cols-3 bg-white/60 shadow-sm">
<TabsTrigger value="tasks">{tc('navigation.tasks')}</TabsTrigger>
<TabsTrigger value="collections">{tc('navigation.collections')}</TabsTrigger>
<TabsTrigger value="emotions">{tc('navigation.emotions')}</TabsTrigger>
</TabsList>
<TenantHeroCard
badge={t('engagement.hero.badge', 'Engagement')}
title={heading}
description={heroDescription}
supporting={heroSupporting}
primaryAction={heroPrimaryAction}
secondaryAction={heroSecondaryAction}
aside={heroAside}
/>
<TabsContent value="tasks" className="space-y-6">
<TasksSection
embedded
onNavigateToCollections={() => handleTabChange('collections')}
/>
</TabsContent>
<FrostedCard className="mt-6 border border-white/20">
<CardHeader className="px-0 pt-0">
<CardTitle className="sr-only">{heading}</CardTitle>
</CardHeader>
<CardContent className="space-y-6">
<Tabs value={activeTab} onValueChange={handleTabChange} className="space-y-6">
<TabsList className="grid w-full grid-cols-3 rounded-2xl border border-white/25 bg-white/80 p-1 shadow-inner shadow-rose-200/20 dark:border-slate-800/70 dark:bg-slate-900/70">
{(['tasks', 'collections', 'emotions'] as const).map((tab) => (
<TabsTrigger
key={tab}
value={tab}
className="rounded-xl text-sm font-medium transition data-[state=active]:bg-gradient-to-r data-[state=active]:from-[#ff5f87] data-[state=active]:via-[#ec4899] data-[state=active]:to-[#6366f1] data-[state=active]:text-white"
>
{tc(`navigation.${tab}`)}
</TabsTrigger>
))}
</TabsList>
<TabsContent value="collections" className="space-y-6">
<TaskCollectionsSection
embedded
onNavigateToTasks={() => handleTabChange('tasks')}
/>
</TabsContent>
<TabsContent value="tasks" className="space-y-6">
<TasksSection embedded onNavigateToCollections={() => handleTabChange('collections')} />
</TabsContent>
<TabsContent value="emotions" className="space-y-6">
<EmotionsSection embedded />
</TabsContent>
</Tabs>
<TabsContent value="collections" className="space-y-6">
<TaskCollectionsSection embedded onNavigateToTasks={() => handleTabChange('tasks')} />
</TabsContent>
<TabsContent value="emotions" className="space-y-6">
<EmotionsSection embedded />
</TabsContent>
</Tabs>
</CardContent>
</FrostedCard>
</AdminLayout>
);
}