reworked the guest pwa, modernized start and gallery page. added share link functionality.

This commit is contained in:
Codex Agent
2025-11-10 22:25:25 +01:00
parent 1e8810ca51
commit 1cec116933
22 changed files with 1208 additions and 476 deletions

View File

@@ -73,30 +73,17 @@ export default function EmotionPicker({ onSelect }: EmotionPickerProps) {
}
};
if (loading) {
return (
<div className="mb-6 p-4 text-center">
<div className="text-sm text-muted-foreground">Lade Emotionen...</div>
const content = (
<div className="space-y-4">
<div className="flex items-center justify-between">
<h3 className="text-base font-semibold">
Wie fühlst du dich?
<span className="ml-2 text-xs text-muted-foreground">(optional)</span>
</h3>
{loading && <span className="text-xs text-muted-foreground">Lade Emotionen</span>}
</div>
);
}
if (error) {
return (
<div className="mb-6 p-4 bg-red-50 border border-red-200 rounded-lg">
<div className="text-sm text-red-700">{error}</div>
</div>
);
}
return (
<div className="mb-6">
<h3 className="text-lg font-semibold mb-4 flex items-center gap-2">
Wie fühlst du dich?
<span className="text-xs text-muted-foreground">(optional)</span>
</h3>
<div className="grid grid-cols-2 md:grid-cols-3 gap-3">
<div className="flex gap-3 overflow-x-auto pb-2 [-ms-overflow-style:none] [scrollbar-width:none]" aria-label="Emotions">
{emotions.map((emotion) => {
// Localize name and description if they are JSON
const localize = (value: string | object, defaultValue: string = ''): string => {
@@ -113,25 +100,26 @@ export default function EmotionPicker({ onSelect }: EmotionPickerProps) {
const localizedName = localize(emotion.name, emotion.name);
const localizedDescription = localize(emotion.description || '', '');
return (
<Button
<button
key={emotion.id}
variant="outline"
className="w-full justify-start h-16 p-3 bg-pink-50 dark:bg-gray-800/50 hover:bg-pink-100 dark:hover:bg-gray-700/50 border-pink-200 dark:border-gray-600 rounded-xl text-left shadow-sm dark:text-white"
type="button"
onClick={() => handleEmotionSelect(emotion)}
className="group flex min-w-[180px] flex-col gap-2 rounded-2xl border border-white/40 bg-white/80 px-4 py-3 text-left shadow-sm transition hover:-translate-y-0.5 hover:border-pink-200 hover:shadow-md dark:border-gray-700/60 dark:bg-gray-900/70"
>
<div className="flex items-center gap-3">
<span className="text-2xl">{emotion.emoji}</span>
<span className="text-2xl" aria-hidden>
{emotion.emoji}
</span>
<div className="flex-1 min-w-0">
<div className="font-medium text-sm truncate">{localizedName}</div>
<div className="font-medium text-sm text-foreground line-clamp-1">{localizedName}</div>
{localizedDescription && (
<div className="text-xs text-muted-foreground truncate">{localizedDescription}</div>
<div className="text-xs text-muted-foreground line-clamp-1">{localizedDescription}</div>
)}
</div>
<ChevronRight className="h-4 w-4 text-muted-foreground ml-auto" />
<ChevronRight className="h-4 w-4 text-muted-foreground opacity-0 transition group-hover:opacity-100" />
</div>
</Button>
</button>
);
})}
</div>
@@ -151,4 +139,18 @@ export default function EmotionPicker({ onSelect }: EmotionPickerProps) {
</div>
</div>
);
if (error) {
return (
<div className="rounded-3xl border border-red-200 bg-red-50 p-4 text-sm text-red-700">
{error}
</div>
);
}
return (
<div className="rounded-3xl border border-muted/40 bg-gradient-to-br from-white to-white/70 p-4 shadow-sm backdrop-blur">
{content}
</div>
);
}