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

@@ -2,9 +2,11 @@ import React, { useState, useEffect } from 'react';
import { useParams, useLocation, useNavigate } from 'react-router-dom';
import { Dialog, DialogContent } from '@/components/ui/dialog';
import { Button } from '@/components/ui/button';
import { Heart, ChevronLeft, ChevronRight, X } from 'lucide-react';
import { Heart, ChevronLeft, ChevronRight, X, Share2 } from 'lucide-react';
import { likePhoto } from '../services/photosApi';
import { useTranslation } from '../i18n/useTranslation';
import { sharePhotoLink } from '../lib/sharePhoto';
import { useToast } from '../components/ToastHost';
type Photo = {
id: number;
@@ -33,6 +35,7 @@ export default function PhotoLightbox({ photos, currentIndex, onClose, onIndexCh
const photoId = params.photoId;
const eventToken = params.token || token;
const { t } = useTranslation();
const toast = useToast();
const [standalonePhoto, setStandalonePhoto] = useState<Photo | null>(null);
const [loading, setLoading] = useState(true);
@@ -41,6 +44,7 @@ export default function PhotoLightbox({ photos, currentIndex, onClose, onIndexCh
const [taskLoading, setTaskLoading] = useState(false);
const [likes, setLikes] = useState<number>(0);
const [liked, setLiked] = useState(false);
const [shareLoading, setShareLoading] = useState(false);
// Determine mode and photo
const isStandalone = !photos || photos.length === 0;
@@ -197,6 +201,30 @@ export default function PhotoLightbox({ photos, currentIndex, onClose, onIndexCh
}
}
async function onShare() {
if (!photo || !eventToken) return;
setShareLoading(true);
try {
const result = await sharePhotoLink({
token: eventToken,
photoId: photo.id,
title: photo.task_title ?? task?.title ?? t('share.title', 'Geteiltes Foto'),
text: t('share.shareText', { event: '' }),
});
if (result.method === 'clipboard') {
toast.push({ text: t('share.copySuccess', 'Link kopiert!') });
} else if (result.method === 'manual') {
window.prompt(t('share.manualPrompt', 'Link kopieren'), result.url);
}
} catch (error) {
console.error('share failed', error);
toast.push({ text: t('share.error', 'Teilen fehlgeschlagen'), type: 'error' });
} finally {
setShareLoading(false);
}
}
function onOpenChange(open: boolean) {
if (!open) handleClose();
}
@@ -216,6 +244,15 @@ export default function PhotoLightbox({ photos, currentIndex, onClose, onIndexCh
<Heart className={`mr-1 h-4 w-4 ${liked ? 'fill-red-400 text-red-400' : ''}`} />
{likes}
</Button>
<Button
variant="secondary"
size="sm"
onClick={onShare}
disabled={shareLoading || !eventToken || !photo}
>
<Share2 className="mr-1 h-4 w-4" />
{t('share.button', 'Teilen')}
</Button>
</div>
<div className="flex items-center gap-1">
{currentIndexVal > 0 && (