umfangreiche Behebung von TS-Fehlern. "npm run types" läuft nun ohne Fehler durch

This commit is contained in:
Codex Agent
2025-11-21 07:45:21 +01:00
parent b6f6cdeffe
commit 07fe049b8a
25 changed files with 74 additions and 63 deletions

View File

@@ -249,7 +249,7 @@ type NotificationButtonProps = {
eventToken: string;
open: boolean;
onToggle: () => void;
panelRef: React.RefObject<HTMLDivElement>;
panelRef: React.RefObject<HTMLDivElement | null>;
checklistItems: string[];
taskProgress?: ReturnType<typeof useGuestTaskProgress>;
t: TranslateFn;
@@ -316,7 +316,7 @@ function NotificationButton({ center, eventToken, open, onToggle, panelRef, chec
<p className="text-sm font-semibold text-slate-900">{t('header.notifications.title', 'Benachrichtigungen')}</p>
<p className="text-xs text-slate-500">
{center.unreadCount > 0
? t('header.notifications.unread', '{{count}} neu', { count: center.unreadCount })
? t('header.notifications.unread', { defaultValue: '{{count}} neu', count: center.unreadCount })
: t('header.notifications.allRead', 'Alles gelesen')}
</p>
</div>

View File

@@ -362,7 +362,7 @@ export const demoFixtures: DemoFixtures = {
],
share: {
slug: 'demo-share',
expires_at: null,
expires_at: undefined,
photo: {
id: 8801,
title: 'First Look',

View File

@@ -104,7 +104,7 @@ export function usePushSubscription(eventToken?: string): PushSubscriptionState
const newSubscription = await registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array(pushConfig.vapidPublicKey),
applicationServerKey: urlBase64ToUint8Array(pushConfig.vapidPublicKey).buffer as ArrayBuffer,
});
await registerPushSubscription(eventToken, newSubscription);

View File

@@ -482,9 +482,6 @@ export const messages: Record<LocaleCode, NestedMessages> = {
optimizedNotice: 'Wir haben dein Foto verkleinert, damit der Upload schneller klappt. Eingespart: {saved}',
optimizedFallback: 'Optimierung nicht möglich wir laden das Original hoch.',
retrying: 'Verbindung holperig neuer Versuch ({attempt}).',
errors: {
tooLargeHint: 'Das Foto war zu groß. Bitte erneut versuchen wir verkleinern es automatisch.',
},
controls: {
toggleGrid: 'Raster umschalten',
toggleCountdown: 'Countdown umschalten',
@@ -560,6 +557,7 @@ export const messages: Record<LocaleCode, NestedMessages> = {
packageMissing: 'Dieses Event akzeptiert derzeit keine Uploads.',
galleryExpired: 'Die Galerie ist abgelaufen. Uploads sind nicht mehr möglich.',
generic: 'Upload fehlgeschlagen. Bitte versuche es erneut.',
tooLargeHint: 'Das Foto war zu groß. Bitte erneut versuchen wir verkleinern es automatisch.',
},
cameraInactive: 'Kamera ist nicht aktiv. {hint}',
cameraInactiveHint: 'Tippe auf "{label}", um loszulegen.',
@@ -1126,9 +1124,6 @@ export const messages: Record<LocaleCode, NestedMessages> = {
optimizedNotice: 'We optimized your photo to speed up the upload. Saved: {saved}',
optimizedFallback: 'Could not optimize uploading the original.',
retrying: 'Connection unstable retrying ({attempt}).',
errors: {
tooLargeHint: 'The photo was too large. Please try again — we compress it automatically.',
},
controls: {
toggleGrid: 'Toggle grid',
toggleCountdown: 'Toggle countdown',
@@ -1204,6 +1199,7 @@ export const messages: Record<LocaleCode, NestedMessages> = {
packageMissing: 'This event is not accepting uploads right now.',
galleryExpired: 'The gallery has expired. Uploads are no longer possible.',
generic: 'Upload failed. Please try again.',
tooLargeHint: 'The photo was too large. Please try again — we compress it automatically.',
},
cameraInactive: 'Camera is not active. {hint}',
cameraInactiveHint: 'Tap "{label}" to get started.',

View File

@@ -19,7 +19,7 @@ export default function HomePage() {
const { name, hydrated } = useGuestIdentity();
const stats = useEventStats();
const { event } = useEventData();
const { completedCount } = useGuestTaskProgress(token);
const { completedCount } = useGuestTaskProgress(token ?? '');
const { t, locale } = useTranslation();
const { branding } = useEventBranding();
@@ -86,15 +86,16 @@ export default function HomePage() {
async function loadMissions() {
setMissionLoading(true);
try {
const response = await fetch(
`/api/v1/events/${encodeURIComponent(token)}/tasks?locale=${encodeURIComponent(locale)}`,
{
headers: {
Accept: 'application/json',
'X-Locale': locale,
},
}
);
const safeToken = token ?? '';
const response = await fetch(
`/api/v1/events/${encodeURIComponent(safeToken)}/tasks?locale=${encodeURIComponent(locale)}`,
{
headers: {
Accept: 'application/json',
'X-Locale': locale,
},
}
);
if (!response.ok) throw new Error('Aufgaben konnten nicht geladen werden.');
const payload = await response.json();
if (cancelled) return;

View File

@@ -30,7 +30,7 @@ const INITIAL_STATE: GalleryState = {
const GALLERY_PAGE_SIZE = 30;
export default function PublicGalleryPage(): JSX.Element | null {
export default function PublicGalleryPage(): React.ReactElement | null {
const { token } = useParams<{ token: string }>();
const { t } = useTranslation();
const [state, setState] = useState<GalleryState>(INITIAL_STATE);

View File

@@ -2,7 +2,7 @@
import { useNavigate, useParams, useSearchParams } from 'react-router-dom';
import { Button } from '@/components/ui/button';
import { Alert, AlertDescription } from '@/components/ui/alert';
import { Sparkles, RefreshCw, Smile, Camera, Timer as TimerIcon, Heart, ChevronRight } from 'lucide-react';
import { Sparkles, RefreshCw, Smile, Camera, Timer as TimerIcon, Heart, ChevronRight, CheckCircle2 } from 'lucide-react';
import type { LucideIcon } from 'lucide-react';
import { useGuestTaskProgress } from '../hooks/useGuestTaskProgress';
import { ToggleGroup, ToggleGroupItem } from '@/components/ui/toggle-group';

View File

@@ -882,7 +882,7 @@ const renderWithDialog = (content: ReactNode, wrapperClassName = 'space-y-6 pb-[
<AlertDescription>
{t('upload.limitReached')
.replace('{used}', `${eventPackage?.used_photos || 0}`)
.replace('{max}', `${eventPackage?.package.max_photos || 0}`)}
.replace('{max}', `${eventPackage?.package?.max_photos || 0}`)}
</AlertDescription>
</Alert>
</>

View File

@@ -147,12 +147,14 @@ export async function getHelpArticle(slug: string, locale: LocaleCode): Promise<
locale,
});
const data = await requestJson<{ data?: HelpArticleDetail }>(`/api/v1/help/${encodeURIComponent(slug)}?${params.toString()}`);
const article = data?.data ?? { slug, title: slug, summary: '' };
writeCache(cacheKey, article);
return { article, servedFromCache: false };
const article: HelpArticleDetail | undefined = data?.data;
const safeArticle: HelpArticleDetail = article ?? { slug, title: slug, summary: '' };
writeCache(cacheKey, safeArticle);
return { article: safeArticle, servedFromCache: false };
} catch (error) {
if (cached) {
return { article: cached.data, servedFromCache: true };
const cachedArticle: HelpArticleDetail | undefined = (cached as { data?: HelpArticleDetail } | null | undefined)?.data;
if (cachedArticle) {
return { article: cachedArticle, servedFromCache: true };
}
console.error('[HelpApi] Failed to fetch help article', error);
throw error;