refactoring

This commit is contained in:
2025-11-10 16:44:54 +01:00
parent c2710f0a67
commit 89e7f77a4e
11 changed files with 807 additions and 10 deletions

View File

@@ -11,6 +11,7 @@ const { scheduleConfig } = require('./services/pickupScheduler');
const adminConfig = require('./services/adminConfig');
const { readNotificationSettings, writeNotificationSettings } = require('./services/userSettingsStore');
const notificationService = require('./services/notificationService');
const { readStoreWatch, writeStoreWatch } = require('./services/storeWatchStore');
const ONE_YEAR_MS = 365 * 24 * 60 * 60 * 1000;
const adminEmail = (process.env.ADMIN_EMAIL || '').toLowerCase();
@@ -20,6 +21,8 @@ const app = express();
const port = process.env.PORT || 3000;
const storeRefreshJobs = new Map();
const cachedStoreSnapshots = new Map();
const regionStoreCache = new Map();
const REGION_STORE_CACHE_MS = 15 * 60 * 1000;
app.use(cors());
app.use(express.json({ limit: '1mb' }));
@@ -88,6 +91,25 @@ function mergeStoresIntoConfig(config = [], stores = []) {
return { merged: Array.from(map.values()), changed };
}
function getCachedRegionStores(regionId) {
const entry = regionStoreCache.get(String(regionId));
if (!entry) {
return null;
}
if (Date.now() - entry.fetchedAt > REGION_STORE_CACHE_MS) {
regionStoreCache.delete(String(regionId));
return null;
}
return entry.payload;
}
function setCachedRegionStores(regionId, payload) {
regionStoreCache.set(String(regionId), {
fetchedAt: Date.now(),
payload
});
}
function isStoreCacheFresh(session) {
if (!session?.storesCache?.fetchedAt) {
return false;
@@ -368,6 +390,79 @@ app.get('/api/profile', requireAuth, async (req, res) => {
});
});
app.get('/api/store-watch/regions', requireAuth, async (req, res) => {
try {
const details = await foodsharingClient.fetchProfile(req.session.cookieHeader);
const regions = Array.isArray(details?.regions)
? details.regions.filter((region) => Number(region?.classification) === 1)
: [];
res.json({ regions });
} catch (error) {
console.error('[STORE-WATCH] Regionen konnten nicht geladen werden:', error.message);
res.status(500).json({ error: 'Regionen konnten nicht geladen werden' });
}
});
app.get('/api/store-watch/regions/:regionId/stores', requireAuth, async (req, res) => {
const { regionId } = req.params;
if (!regionId) {
return res.status(400).json({ error: 'Region-ID fehlt' });
}
const forceRefresh = req.query.force === '1';
if (!forceRefresh) {
const cached = getCachedRegionStores(regionId);
if (cached) {
return res.json(cached);
}
}
try {
const result = await foodsharingClient.fetchRegionStores(regionId, req.session.cookieHeader);
const payload = {
total: Number(result?.total) || 0,
stores: Array.isArray(result?.stores) ? result.stores : []
};
setCachedRegionStores(regionId, payload);
res.json(payload);
} catch (error) {
console.error(`[STORE-WATCH] Stores für Region ${regionId} konnten nicht geladen werden:`, error.message);
res.status(500).json({ error: 'Betriebe konnten nicht geladen werden' });
}
});
app.get('/api/store-watch/subscriptions', requireAuth, (req, res) => {
const stores = readStoreWatch(req.session.profile.id);
res.json({ stores });
});
app.post('/api/store-watch/subscriptions', requireAuth, (req, res) => {
if (!req.body || !Array.isArray(req.body.stores)) {
return res.status(400).json({ error: 'Erwartet eine Liste von Betrieben' });
}
const previous = readStoreWatch(req.session.profile.id);
const previousMap = new Map(previous.map((entry) => [entry.storeId, entry]));
const normalized = [];
req.body.stores.forEach((store) => {
const storeId = store?.storeId || store?.id;
const regionId = store?.regionId || store?.region?.id;
if (!storeId || !regionId) {
return;
}
const entry = {
storeId: String(storeId),
storeName: store?.storeName || store?.name || `Store ${storeId}`,
regionId: String(regionId),
regionName: store?.regionName || store?.region?.name || '',
lastTeamSearchStatus: previousMap.get(String(storeId))?.lastTeamSearchStatus ?? null
};
normalized.push(entry);
});
const persisted = writeStoreWatch(req.session.profile.id, normalized);
const config = readConfig(req.session.profile.id);
scheduleWithCurrentSettings(req.session.id, config);
res.json({ success: true, stores: persisted });
});
app.get('/api/config', requireAuth, (req, res) => {
const config = readConfig(req.session.profile.id);
res.json(config);