news widget design 5

This commit is contained in:
alma 2025-04-14 20:36:52 +02:00
parent 0496f90d32
commit 81ead6d121

View File

@ -1,7 +1,7 @@
import { NextResponse } from 'next/server'; import { NextResponse } from 'next/server';
// FastAPI server configuration // FastAPI server configuration - use localhost since both servers are on the same machine
const API_HOST = process.env.API_HOST || 'http://172.16.0.104:8000'; const API_HOST = process.env.API_HOST || 'http://localhost:8000';
// Helper function to clean HTML content // Helper function to clean HTML content
function cleanHtmlContent(content: string): string { function cleanHtmlContent(content: string): string {
@ -16,22 +16,24 @@ function cleanHtmlContent(content: string): string {
} }
// Helper function to format time // Helper function to format time
function formatDateTime(dateStr: string): { date: string, time: string } { function formatDateTime(dateStr: string): { displayDate: string, timestamp: string } {
try { try {
const date = new Date(dateStr); const date = new Date(dateStr);
const day = date.getDate();
const month = date.toLocaleString('fr-FR', { month: 'short' }).toLowerCase();
return { return {
date: date.toLocaleDateString('fr-FR', { displayDate: `${day} ${month}`,
day: 'numeric', timestamp: date.toLocaleString('fr-FR', {
month: 'short' day: '2-digit',
}), month: 'short',
time: date.toLocaleTimeString('fr-FR', {
hour: '2-digit', hour: '2-digit',
minute: '2-digit', minute: '2-digit',
hour12: false hour12: false
}) })
}; };
} catch (error) { } catch (error) {
return { date: 'N/A', time: 'N/A' }; return { displayDate: 'N/A', timestamp: 'N/A' };
} }
} }
@ -42,15 +44,35 @@ function truncateText(text: string, maxLength: number): string {
return truncated.replace(/[.,!?]$/, '') + '...'; return truncated.replace(/[.,!?]$/, '') + '...';
} }
// Helper function to format category
function formatCategory(category: string): string {
if (!category) return 'GENERAL';
// Simplify long category names
return category
.split('-')
.map(part => part.trim().toUpperCase())
.join(' - ');
}
// Helper function to format source // Helper function to format source
function formatSource(source: string): string { function formatSource(source: string): string {
if (!source) return ''; if (!source) return '';
return source.replace(/^(https?:\/\/)?(www\.)?/i, '').split('.')[0].toLowerCase(); // Extract domain name without TLD and clean it up
const sourceName = source
.replace(/^(https?:\/\/)?(www\.)?/i, '')
.split('.')[0]
.toLowerCase()
.replace(/[^a-z0-9]/g, ' ')
.trim();
return sourceName.charAt(0).toUpperCase() + sourceName.slice(1);
} }
export async function GET() { export async function GET() {
try { try {
console.log(`Fetching news from FastAPI server at ${API_HOST}...`); console.log(`Attempting to connect to FastAPI server at ${API_HOST}...`);
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 5000);
const response = await fetch(`${API_HOST}/news?limit=10`, { const response = await fetch(`${API_HOST}/news?limit=10`, {
method: 'GET', method: 'GET',
@ -59,8 +81,12 @@ export async function GET() {
'Accept': 'application/json', 'Accept': 'application/json',
}, },
cache: 'no-store', cache: 'no-store',
signal: controller.signal,
keepalive: true,
}); });
clearTimeout(timeoutId);
if (!response.ok) { if (!response.ok) {
const errorText = await response.text(); const errorText = await response.text();
throw new Error(`HTTP error! status: ${response.status}, body: ${errorText}`); throw new Error(`HTTP error! status: ${response.status}, body: ${errorText}`);
@ -70,15 +96,15 @@ export async function GET() {
// Format and clean the news data // Format and clean the news data
const formattedNews = rawNews.map((article: any) => { const formattedNews = rawNews.map((article: any) => {
const { date, time } = formatDateTime(article.date); const { displayDate, timestamp } = formatDateTime(article.date);
return { return {
id: article.id, id: article.id,
title: truncateText(cleanHtmlContent(article.title), 100), title: truncateText(cleanHtmlContent(article.title), 100),
description: truncateText(cleanHtmlContent(article.description), 150), description: truncateText(cleanHtmlContent(article.description), 150),
date, displayDate,
time, timestamp,
source: formatSource(article.source), source: formatSource(article.source),
category: (article.category || 'GENERAL').toUpperCase(), category: formatCategory(article.category),
url: article.url || '#', url: article.url || '#',
}; };
}); });