widget news fetch 4
This commit is contained in:
parent
5453b7ef15
commit
f099cf0d6c
@ -1,11 +1,19 @@
|
|||||||
import { NextResponse } from 'next/server';
|
import { NextResponse } from 'next/server';
|
||||||
import { Pool } from 'pg';
|
import { Pool } from 'pg';
|
||||||
|
|
||||||
|
// Function to clean database host URL
|
||||||
|
function cleanDatabaseHost(host: string | undefined): string {
|
||||||
|
if (!host) {
|
||||||
|
throw new Error('Database host is not defined');
|
||||||
|
}
|
||||||
|
return host.replace(/^https?:\/\//, '');
|
||||||
|
}
|
||||||
|
|
||||||
// Create a new pool using the environment variables
|
// Create a new pool using the environment variables
|
||||||
const pool = new Pool({
|
const pool = new Pool({
|
||||||
user: process.env.DB_USER,
|
user: process.env.DB_USER,
|
||||||
password: process.env.DB_PASSWORD,
|
password: process.env.DB_PASSWORD,
|
||||||
host: process.env.DB_HOST?.replace('@https://', ''),
|
host: cleanDatabaseHost(process.env.DB_HOST),
|
||||||
database: process.env.DB_NAME,
|
database: process.env.DB_NAME,
|
||||||
ssl: {
|
ssl: {
|
||||||
rejectUnauthorized: false // Required for some cloud databases
|
rejectUnauthorized: false // Required for some cloud databases
|
||||||
@ -14,11 +22,21 @@ const pool = new Pool({
|
|||||||
|
|
||||||
export async function GET() {
|
export async function GET() {
|
||||||
try {
|
try {
|
||||||
|
// Log connection attempt
|
||||||
|
console.log('Attempting database connection with config:', {
|
||||||
|
user: process.env.DB_USER,
|
||||||
|
host: process.env.DB_HOST,
|
||||||
|
database: process.env.DB_NAME,
|
||||||
|
hasPassword: !!process.env.DB_PASSWORD
|
||||||
|
});
|
||||||
|
|
||||||
// Connect to the database
|
// Connect to the database
|
||||||
const client = await pool.connect();
|
const client = await pool.connect();
|
||||||
|
console.log('Successfully connected to database');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Query the news table for the latest 10 news items
|
// Query the news table for the latest 10 news items
|
||||||
|
console.log('Executing news query...');
|
||||||
const result = await client.query(`
|
const result = await client.query(`
|
||||||
SELECT
|
SELECT
|
||||||
id,
|
id,
|
||||||
@ -37,6 +55,8 @@ export async function GET() {
|
|||||||
LIMIT 10
|
LIMIT 10
|
||||||
`);
|
`);
|
||||||
|
|
||||||
|
console.log(`Query completed. Found ${result.rows.length} news items.`);
|
||||||
|
|
||||||
// Format the response
|
// Format the response
|
||||||
const news = result.rows.map(row => ({
|
const news = result.rows.map(row => ({
|
||||||
id: row.id,
|
id: row.id,
|
||||||
@ -55,14 +75,34 @@ export async function GET() {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
return NextResponse.json({ news });
|
return NextResponse.json({ news });
|
||||||
|
} catch (queryError: any) {
|
||||||
|
console.error('Query error:', queryError);
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: 'Database query failed: ' + (queryError?.message || 'Unknown error') },
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
} finally {
|
} finally {
|
||||||
// Release the client back to the pool
|
// Release the client back to the pool
|
||||||
client.release();
|
client.release();
|
||||||
|
console.log('Database client released');
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error: any) {
|
||||||
console.error('Database connection error:', error);
|
console.error('Database connection error:', error);
|
||||||
|
// Check if error is due to missing configuration
|
||||||
|
if (!process.env.DB_USER || !process.env.DB_PASSWORD || !process.env.DB_HOST || !process.env.DB_NAME) {
|
||||||
|
console.error('Missing database configuration:', {
|
||||||
|
hasUser: !!process.env.DB_USER,
|
||||||
|
hasPassword: !!process.env.DB_PASSWORD,
|
||||||
|
hasHost: !!process.env.DB_HOST,
|
||||||
|
hasDatabase: !!process.env.DB_NAME
|
||||||
|
});
|
||||||
return NextResponse.json(
|
return NextResponse.json(
|
||||||
{ error: 'Failed to fetch news' },
|
{ error: 'Database configuration is incomplete' },
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: 'Failed to connect to database: ' + (error?.message || 'Unknown error') },
|
||||||
{ status: 500 }
|
{ status: 500 }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,95 +24,54 @@ interface NewsItem {
|
|||||||
symbol: string | null;
|
symbol: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mock data for testing - remove this in production
|
|
||||||
const MOCK_NEWS = [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
title: "New Project Management Features Released",
|
|
||||||
url: "#",
|
|
||||||
date: "2024-03-20",
|
|
||||||
source: "Internal",
|
|
||||||
description: "New features added to improve project management workflow",
|
|
||||||
category: "Update",
|
|
||||||
sentiment: { score: null, label: null },
|
|
||||||
symbols: null,
|
|
||||||
symbol: null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
title: "Team Meeting Schedule Changes",
|
|
||||||
url: "#",
|
|
||||||
date: "2024-03-19",
|
|
||||||
source: "Internal",
|
|
||||||
description: "Updates to the team meeting schedule",
|
|
||||||
category: "Announcement",
|
|
||||||
sentiment: { score: null, label: null },
|
|
||||||
symbols: null,
|
|
||||||
symbol: null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
title: "Upcoming Training Sessions",
|
|
||||||
url: "#",
|
|
||||||
date: "2024-03-18",
|
|
||||||
source: "Internal",
|
|
||||||
description: "Schedule for upcoming training sessions",
|
|
||||||
category: "Training",
|
|
||||||
sentiment: { score: null, label: null },
|
|
||||||
symbols: null,
|
|
||||||
symbol: null
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
export function News() {
|
export function News() {
|
||||||
console.log('News component mounted');
|
|
||||||
const [news, setNews] = useState<NewsItem[]>([]);
|
const [news, setNews] = useState<NewsItem[]>([]);
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
const [refreshing, setRefreshing] = useState(false);
|
const [refreshing, setRefreshing] = useState(false);
|
||||||
const [dbStatus, setDbStatus] = useState<'connecting' | 'connected' | 'error'>('connecting');
|
const [dbStatus, setDbStatus] = useState<'connecting' | 'connected' | 'error'>('connecting');
|
||||||
|
|
||||||
|
// Debug info display component
|
||||||
|
const DebugInfo = () => (
|
||||||
|
<div className="text-xs text-gray-500 mt-2 p-2 bg-gray-100 rounded">
|
||||||
|
<p>Status: {dbStatus}</p>
|
||||||
|
<p>Loading: {loading ? 'true' : 'false'}</p>
|
||||||
|
<p>Error: {error || 'none'}</p>
|
||||||
|
<p>News items: {news.length}</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
const fetchNews = async (isRefresh = false) => {
|
const fetchNews = async (isRefresh = false) => {
|
||||||
console.log('Fetching news...');
|
|
||||||
if (isRefresh) setRefreshing(true);
|
if (isRefresh) setRefreshing(true);
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
setDbStatus('connecting');
|
setDbStatus('connecting');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
console.log('Making API request to /api/news');
|
const response = await fetch('/api/news', {
|
||||||
const response = await fetch('/api/news');
|
method: 'GET',
|
||||||
console.log('API response status:', response.status);
|
headers: {
|
||||||
|
'Accept': 'application/json',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
console.log('API request failed');
|
throw new Error(`HTTP error! status: ${response.status}`);
|
||||||
throw new Error('Failed to fetch news');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
console.log('API response data:', data);
|
|
||||||
|
|
||||||
if (data.error) {
|
if (data.error) {
|
||||||
console.log('API returned error:', data.error);
|
|
||||||
throw new Error(data.error);
|
throw new Error(data.error);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If no news items returned, use mock data for testing
|
setNews(data.news || []);
|
||||||
if (!data.news || data.news.length === 0) {
|
|
||||||
console.log('No news items returned, using mock data');
|
|
||||||
setNews(MOCK_NEWS);
|
|
||||||
} else {
|
|
||||||
console.log('Setting news items from API');
|
|
||||||
setNews(data.news);
|
|
||||||
}
|
|
||||||
|
|
||||||
setError(null);
|
setError(null);
|
||||||
setDbStatus('connected');
|
setDbStatus('connected');
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Error details:', err);
|
const errorMessage = err instanceof Error ? err.message : 'Failed to load news';
|
||||||
setError('Failed to load news. Please try again later.');
|
setError(errorMessage);
|
||||||
setDbStatus('error');
|
setDbStatus('error');
|
||||||
console.log('Using mock data due to error');
|
setNews([]);
|
||||||
setNews(MOCK_NEWS);
|
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
setRefreshing(false);
|
setRefreshing(false);
|
||||||
@ -136,33 +95,7 @@ export function News() {
|
|||||||
{dbStatus === 'connecting' ? 'Connecting to database...' : 'Loading news...'}
|
{dbStatus === 'connecting' ? 'Connecting to database...' : 'Loading news...'}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
<DebugInfo />
|
||||||
</Card>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
return (
|
|
||||||
<Card className="w-full">
|
|
||||||
<CardHeader className="flex flex-row items-center justify-between">
|
|
||||||
<CardTitle>News</CardTitle>
|
|
||||||
<Button
|
|
||||||
variant="ghost"
|
|
||||||
size="icon"
|
|
||||||
onClick={() => fetchNews(true)}
|
|
||||||
disabled={refreshing}
|
|
||||||
className={`${refreshing ? 'animate-spin' : ''}`}
|
|
||||||
>
|
|
||||||
<RefreshCw className="h-4 w-4" />
|
|
||||||
</Button>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent>
|
|
||||||
<div className="text-red-500 space-y-2">
|
|
||||||
<p>{error}</p>
|
|
||||||
<p className="text-sm text-gray-500">
|
|
||||||
{dbStatus === 'error' ? 'Database connection error' : 'Failed to fetch news'}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
@ -184,7 +117,14 @@ export function News() {
|
|||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
{news.length === 0 ? (
|
{error ? (
|
||||||
|
<div className="text-red-500 space-y-2">
|
||||||
|
<p>{error}</p>
|
||||||
|
<p className="text-sm text-gray-500">
|
||||||
|
{dbStatus === 'error' ? 'Database connection error' : 'Failed to fetch news'}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
) : news.length === 0 ? (
|
||||||
<div className="text-center text-gray-500 py-8">
|
<div className="text-center text-gray-500 py-8">
|
||||||
No news available
|
No news available
|
||||||
</div>
|
</div>
|
||||||
@ -238,6 +178,7 @@ export function News() {
|
|||||||
))
|
))
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
<DebugInfo />
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user