typescript-typenfehler behoben.. npm run lint läuft nun fehlerfrei durch.

This commit is contained in:
Codex Agent
2025-11-22 11:49:47 +01:00
parent 6c78d7e281
commit eb41cb6194
74 changed files with 469 additions and 396 deletions

View File

@@ -1,7 +1,8 @@
import { useEffect, useRef, useState } from 'react';
import { useCallback, useEffect, useRef, useState } from 'react';
import type { LocaleCode } from '../i18n/messages';
type Photo = { id: number; file_path?: string; thumbnail_path?: string; created_at?: string };
type Photo = { id: number; file_path?: string; thumbnail_path?: string; created_at?: string; session_id?: string | null };
type RawPhoto = Record<string, unknown>;
export function usePollGalleryDelta(token: string, locale: LocaleCode) {
const [photos, setPhotos] = useState<Photo[]>([]);
@@ -14,7 +15,7 @@ export function usePollGalleryDelta(token: string, locale: LocaleCode) {
typeof document !== 'undefined' ? document.visibilityState === 'visible' : true
);
async function fetchDelta() {
const fetchDelta = useCallback(async () => {
if (!token) {
setLoading(false);
return;
@@ -56,9 +57,9 @@ export function usePollGalleryDelta(token: string, locale: LocaleCode) {
Array.isArray(json) ? json :
json.photos || [];
const newPhotos = rawPhotos.map((photo: any) => ({
...photo,
session_id: photo?.session_id ?? photo?.guest_name ?? null,
const newPhotos: Photo[] = rawPhotos.map((photo: RawPhoto) => ({
...(photo as Photo),
session_id: typeof photo.session_id === 'string' ? photo.session_id : (photo.guest_name as string | null) ?? null,
}));
if (newPhotos.length > 0) {
@@ -67,11 +68,9 @@ export function usePollGalleryDelta(token: string, locale: LocaleCode) {
if (latestAt.current) {
// Delta mode: Add new photos to existing list
const merged = [...newPhotos, ...photos];
// Remove duplicates by ID
const uniquePhotos = merged.filter((photo, index, self) =>
index === self.findIndex(p => p.id === photo.id)
);
setPhotos(uniquePhotos);
const byId = new Map<number, Photo>();
merged.forEach((photo) => byId.set(photo.id, photo));
setPhotos(Array.from(byId.values()));
if (added > 0) setNewCount((c) => c + added);
} else {
// Initial load: Set all photos
@@ -83,8 +82,8 @@ export function usePollGalleryDelta(token: string, locale: LocaleCode) {
latestAt.current = json.latest_photo_at;
} else if (newPhotos.length > 0) {
// Fallback: use newest photo timestamp
const newest = newPhotos.reduce((latest: number, photo: any) => {
const photoTime = new Date(photo.created_at || photo.created_at_timestamp || 0).getTime();
const newest = newPhotos.reduce((latest: number, photo: RawPhoto) => {
const photoTime = new Date((photo.created_at as string | undefined) || (photo.created_at_timestamp as number | undefined) || 0).getTime();
return photoTime > latest ? photoTime : latest;
}, 0);
latestAt.current = new Date(newest).toISOString();
@@ -104,7 +103,7 @@ export function usePollGalleryDelta(token: string, locale: LocaleCode) {
setLoading(false);
// Don't update state on error - keep previous photos
}
}
}, [locale, photos, token]);
useEffect(() => {
const onVis = () => setVisible(document.visibilityState === 'visible');
@@ -123,15 +122,15 @@ export function usePollGalleryDelta(token: string, locale: LocaleCode) {
latestAt.current = null;
etagRef.current = null;
setPhotos([]);
fetchDelta();
void fetchDelta();
if (timer.current) window.clearInterval(timer.current);
// Poll less aggressively when hidden
const interval = visible ? 30_000 : 90_000;
timer.current = window.setInterval(fetchDelta, interval);
timer.current = window.setInterval(() => { void fetchDelta(); }, interval);
return () => {
if (timer.current) window.clearInterval(timer.current);
};
}, [token, visible, locale]);
}, [token, visible, locale, fetchDelta]);
function acknowledgeNew() { setNewCount(0); }
return { loading, photos, newCount, acknowledgeNew };