import { useCallback, useEffect, useMemo, useState } from 'react'; const StoreWatchPage = ({ authorizedFetch }) => { const [regions, setRegions] = useState([]); const [selectedRegionId, setSelectedRegionId] = useState(''); const [storesByRegion, setStoresByRegion] = useState({}); const [watchList, setWatchList] = useState([]); const [regionLoading, setRegionLoading] = useState(false); const [storesLoading, setStoresLoading] = useState(false); const [subscriptionsLoading, setSubscriptionsLoading] = useState(false); const [status, setStatus] = useState(''); const [error, setError] = useState(''); const [dirty, setDirty] = useState(false); const [saving, setSaving] = useState(false); const watchedIds = useMemo( () => new Set(watchList.map((entry) => String(entry.storeId))), [watchList] ); const selectedRegion = useMemo( () => regions.find((region) => String(region.id) === String(selectedRegionId)) || null, [regions, selectedRegionId] ); const currentStores = useMemo(() => { const regionEntry = storesByRegion[String(selectedRegionId)]; if (!regionEntry || !Array.isArray(regionEntry.stores)) { return []; } return regionEntry.stores; }, [storesByRegion, selectedRegionId]); const eligibleStores = useMemo( () => currentStores.filter((store) => Number(store.cooperationStatus) === 5), [currentStores] ); const loadRegions = useCallback(async () => { if (!authorizedFetch) { return; } setRegionLoading(true); setError(''); try { const response = await authorizedFetch('/api/store-watch/regions'); if (!response.ok) { throw new Error(`HTTP ${response.status}`); } const data = await response.json(); const normalized = Array.isArray(data.regions) ? data.regions : []; setRegions(normalized); if (!selectedRegionId && normalized.length > 0) { setSelectedRegionId(String(normalized[0].id)); } } catch (err) { setError(`Regionen konnten nicht geladen werden: ${err.message}`); } finally { setRegionLoading(false); } }, [authorizedFetch, selectedRegionId]); const loadSubscriptions = useCallback(async () => { if (!authorizedFetch) { return; } setSubscriptionsLoading(true); setError(''); try { const response = await authorizedFetch('/api/store-watch/subscriptions'); if (!response.ok) { throw new Error(`HTTP ${response.status}`); } const data = await response.json(); const normalized = Array.isArray(data.stores) ? data.stores : []; setWatchList(normalized); setDirty(false); } catch (err) { setError(`Überwachte Betriebe konnten nicht geladen werden: ${err.message}`); } finally { setSubscriptionsLoading(false); } }, [authorizedFetch]); const fetchStoresForRegion = useCallback( async (regionId, { force } = {}) => { if (!authorizedFetch || !regionId) { return; } if (!force && storesByRegion[String(regionId)]) { return; } setStoresLoading(true); setError(''); try { const endpoint = force ? `/api/store-watch/regions/${regionId}/stores?force=1` : `/api/store-watch/regions/${regionId}/stores`; const response = await authorizedFetch(endpoint); if (!response.ok) { throw new Error(`HTTP ${response.status}`); } const data = await response.json(); setStoresByRegion((prev) => ({ ...prev, [String(regionId)]: { total: Number(data.total) || 0, stores: Array.isArray(data.stores) ? data.stores : [], fetchedAt: Date.now() } })); } catch (err) { setError(`Betriebe konnten nicht geladen werden: ${err.message}`); } finally { setStoresLoading(false); } }, [authorizedFetch, storesByRegion] ); useEffect(() => { loadRegions(); loadSubscriptions(); }, [loadRegions, loadSubscriptions]); useEffect(() => { if (selectedRegionId) { fetchStoresForRegion(selectedRegionId); } }, [selectedRegionId, fetchStoresForRegion]); const handleToggleStore = useCallback( (store, checked) => { setWatchList((prev) => { const storeId = String(store.id || store.storeId); const existing = prev.find((entry) => entry.storeId === storeId); if (checked) { if (existing) { return prev; } setDirty(true); const regionName = store.region?.name || selectedRegion?.name || existing?.regionName || ''; return [ ...prev, { storeId, storeName: store.name || store.storeName || `Store ${storeId}`, regionId: String(store.region?.id || selectedRegionId || existing?.regionId || ''), regionName, lastTeamSearchStatus: existing?.lastTeamSearchStatus ?? null } ]; } if (!existing) { return prev; } setDirty(true); return prev.filter((entry) => entry.storeId !== storeId); }); }, [selectedRegion, selectedRegionId] ); const handleRemoveWatch = useCallback((storeId) => { setWatchList((prev) => { const next = prev.filter((entry) => entry.storeId !== storeId); if (next.length !== prev.length) { setDirty(true); } return next; }); }, []); const handleSave = useCallback(async () => { if (!authorizedFetch || saving || !dirty) { return; } setSaving(true); setStatus(''); setError(''); try { const response = await authorizedFetch('/api/store-watch/subscriptions', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ stores: watchList }) }); if (!response.ok) { throw new Error(`HTTP ${response.status}`); } const data = await response.json(); setWatchList(Array.isArray(data.stores) ? data.stores : []); setDirty(false); setStatus('Überwachung gespeichert.'); setTimeout(() => setStatus(''), 4000); } catch (err) { setError(`Speichern fehlgeschlagen: ${err.message}`); } finally { setSaving(false); } }, [authorizedFetch, dirty, saving, watchList]); const handleReset = useCallback(() => { loadSubscriptions(); }, [loadSubscriptions]); if (!authorizedFetch) { return (
Keine Session aktiv.
Wähle Betriebe aus, die bei offenem Team-Status automatisch gemeldet werden sollen.
Es werden nur Regionen angezeigt, in denen du Mitglied mit Klassifikation 1 bist.
Lade Betriebe...
} {!storesLoading && (!selectedRegionId || eligibleStores.length === 0) && ({selectedRegionId ? 'Keine geeigneten Betriebe (Status "aktiv") in dieser Region.' : 'Bitte zuerst eine Region auswählen.'}
)} {!storesLoading && eligibleStores.length > 0 && (| Betrieb | Ort | Kooperation | Überwachen |
|---|---|---|---|
|
{store.name} #{store.id} |
{store.city || 'unbekannt'} {store.street || ''} |
Seit {store.createdAt ? new Date(store.createdAt).toLocaleDateString('de-DE') : 'n/a'} | handleToggleStore(store, event.target.checked)} /> |
Lade aktuelle Auswahl...
} {!subscriptionsLoading && watchList.length === 0 && (Noch keine Betriebe ausgewählt.
)} {watchList.length > 0 && ({entry.storeName}
#{entry.storeId} — {entry.regionName || 'Region unbekannt'}
Letzter Status:{' '} {entry.lastTeamSearchStatus === 1 ? 'Suchend' : entry.lastTeamSearchStatus === 0 ? 'Nicht suchend' : 'Unbekannt'}
Es gibt ungespeicherte Änderungen. Bitte "Speichern" klicken.
)}