Add news widget functionality: Integrate newsRouter for fetching news data, update initializeWidgetTypes to include news endpoint, and enhance DashboardWidget component to display news articles with pagination support. Update LoggedInView to manage widget request counters for unique endpoint handling.

This commit is contained in:
Torsten Schulz (local)
2026-01-29 17:20:06 +01:00
parent 62d8cd7b05
commit e8c6f6ffb9
7 changed files with 188 additions and 14 deletions

View File

@@ -0,0 +1,70 @@
/**
* Proxy für newsdata.io API.
* Endpoint: https://newsdata.io/api/1/news?apikey=...&language=...&category=...
* Pagination: counter = wievieltes Widget dieser Art (0 = erste Seite, 1 = zweite, …), damit News nicht doppelt gezeigt werden.
*/
const NEWS_BASE = 'https://newsdata.io/api/1/news';
/**
* @param {object} options
* @param {number} options.counter - 0 = erste Seite, 1 = zweite, … (für Pagination/nextPage)
* @param {string} [options.language] - z. B. de, en
* @param {string} [options.category] - z. B. top, technology
* @returns {Promise<{ results: Array, nextPage: string|null }>}
*/
async function fetchNewsPage({ counter, language = 'de', category = 'top', nextPageToken = null }) {
const apiKey = process.env.NEWSDATA_IO_API_KEY;
if (!apiKey || !apiKey.trim()) {
throw new Error('NEWSDATA_IO_API_KEY is not set in .env');
}
const params = new URLSearchParams();
params.set('apikey', apiKey.trim());
params.set('language', String(language));
params.set('category', String(category));
if (nextPageToken) params.set('page', nextPageToken);
const url = `${NEWS_BASE}?${params.toString()}`;
const res = await fetch(url);
if (!res.ok) {
const text = await res.text();
throw new Error(`newsdata.io: ${res.status} ${text.slice(0, 200)}`);
}
const data = await res.json();
return {
results: data.results ?? [],
nextPage: data.nextPage ?? null
};
}
/**
* Liefert die Seite für das „counter.“-te Widget (0 = erste Seite, 1 = zweite, …).
* Ruft die API ggf. mehrfach auf (nextPage), damit jede Widget-Instanz andere Artikel bekommt.
*
* @param {object} options
* @param {number} options.counter
* @param {string} [options.language]
* @param {string} [options.category]
* @returns {Promise<{ results: Array, nextPage: string|null }>}
*/
async function getNews({ counter = 0, language = 'de', category = 'top' }) {
let nextPageToken = null;
let lastResult = { results: [], nextPage: null };
for (let i = 0; i <= counter; i++) {
lastResult = await fetchNewsPage({
counter: i,
language,
category,
nextPageToken: nextPageToken || undefined
});
nextPageToken = lastResult.nextPage;
if (!nextPageToken && i < counter) {
break;
}
}
return lastResult;
}
export default { getNews };