news widget design 5
This commit is contained in:
parent
0496f90d32
commit
81ead6d121
@ -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 || '#',
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user