Merge pull request #5 from newspedia-crew/intern-change
Change the logic of loading file
This commit is contained in:
commit
ebfae3abd8
16 changed files with 115 additions and 37 deletions
|
@ -1,2 +1,2 @@
|
||||||
NEXT_PUBLIC_WS_URL=ws://localhost:3001
|
NEXT_PUBLIC_WS_URL=ws://localhost:3000
|
||||||
NEXT_PUBLIC_API_URL=http://localhost:3001/api
|
NEXT_PUBLIC_API_URL=http://localhost:3000/api
|
22
ui/app/api/news/[id]/route.ts
Normal file
22
ui/app/api/news/[id]/route.ts
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
import { NextResponse } from "next/server";
|
||||||
|
import fs from "node:fs/promises";
|
||||||
|
import path from "node:path";
|
||||||
|
import { VALIDATED_ENV } from "../../../../lib/constants";
|
||||||
|
|
||||||
|
export async function GET(request: Request, { params }: { params: { id: string } }) {
|
||||||
|
try {
|
||||||
|
console.log(`Fetching news data for id: ${params.id}`);
|
||||||
|
console.log(`API URL: ${VALIDATED_ENV.API_URL}`); // Log the API URL
|
||||||
|
|
||||||
|
const dataDirectory = path.join(process.cwd(), "public", "data");
|
||||||
|
const filePath = path.join(dataDirectory, `${params.id}.json`);
|
||||||
|
const fileContents = await fs.readFile(filePath, "utf8");
|
||||||
|
const newsData = JSON.parse(fileContents);
|
||||||
|
|
||||||
|
return NextResponse.json(newsData);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error reading news data:", error);
|
||||||
|
console.log(`WS URL: ${VALIDATED_ENV.WS_URL}`); // Log the WebSocket URL, just as an example
|
||||||
|
return NextResponse.json({ error: "News not found" }, { status: 404 });
|
||||||
|
}
|
||||||
|
}
|
16
ui/app/api/news/route.ts
Normal file
16
ui/app/api/news/route.ts
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
import { NextResponse } from "next/server";
|
||||||
|
import fs from "node:fs/promises";
|
||||||
|
import path from "node:path";
|
||||||
|
|
||||||
|
export async function GET() {
|
||||||
|
try {
|
||||||
|
const dataDirectory = path.join(process.cwd(), "public", "data");
|
||||||
|
const filePath = path.join(dataDirectory, "index.json");
|
||||||
|
const fileContents = await fs.readFile(filePath, "utf8");
|
||||||
|
const data = JSON.parse(fileContents);
|
||||||
|
return NextResponse.json(data);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error reading news data:", error);
|
||||||
|
return NextResponse.json({ error: "Failed to load news data" }, { status: 500 });
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,17 +1,15 @@
|
||||||
import Link from "next/link";
|
import { Metadata } from "next";
|
||||||
import { ArrowLeft } from "lucide-react";
|
import React from "react";
|
||||||
|
import { ENV, assertEnvVariables } from "../../../lib/constants";
|
||||||
|
|
||||||
export default function NewsDetailLayout({ children }: { children: React.ReactNode }) {
|
export const metadata: Metadata = {
|
||||||
return (
|
title: "News - Perplexica",
|
||||||
<div className="max-w-4xl mx-auto p-4">
|
};
|
||||||
<Link
|
|
||||||
href="/news"
|
assertEnvVariables(ENV);
|
||||||
className="inline-flex items-center mb-4 text-sm font-medium text-black dark:text-white hover:underline"
|
|
||||||
>
|
const Layout = ({ children }: { children: React.ReactNode }) => {
|
||||||
<ArrowLeft className="w-4 h-4 mr-1" />
|
return <div>{children}</div>;
|
||||||
Back
|
};
|
||||||
</Link>
|
|
||||||
{children}
|
export default Layout;
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,11 +1,19 @@
|
||||||
import { fetchNewsData } from "../../../lib/fetchNewsData";
|
|
||||||
import NewsDetail from "../../../components/NewsDetail";
|
import NewsDetail from "../../../components/NewsDetail";
|
||||||
|
import { VALIDATED_ENV } from "../../../lib/constants";
|
||||||
|
|
||||||
|
async function getNewsData(id: string) {
|
||||||
|
const res = await fetch(`${VALIDATED_ENV.API_URL}/news/${id}`, { next: { revalidate: 60 } });
|
||||||
|
if (!res.ok) {
|
||||||
|
throw new Error("Failed to fetch news");
|
||||||
|
}
|
||||||
|
return res.json();
|
||||||
|
}
|
||||||
|
|
||||||
export default async function NewsPage({ params }: { params: { id: string } }) {
|
export default async function NewsPage({ params }: { params: { id: string } }) {
|
||||||
const newsData = await fetchNewsData(params.id);
|
const newsData = await getNewsData(params.id);
|
||||||
|
|
||||||
if (!newsData) {
|
if (!newsData) {
|
||||||
return <div>News not found</div>;
|
return <div className="text-center text-red-500">News not found or failed to load</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
return <NewsDetail news={newsData} />;
|
return <NewsDetail news={newsData} />;
|
||||||
|
|
|
@ -7,7 +7,14 @@ interface ContextItemProperties {
|
||||||
name: string;
|
name: string;
|
||||||
url: string;
|
url: string;
|
||||||
description: string;
|
description: string;
|
||||||
provider: { name: string; image?: { thumbnail: { contentUrl: string } } }[];
|
provider: {
|
||||||
|
name: string;
|
||||||
|
image?: {
|
||||||
|
thumbnail: {
|
||||||
|
contentUrl: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}[];
|
||||||
datePublished: string;
|
datePublished: string;
|
||||||
image?: {
|
image?: {
|
||||||
contentUrl: string;
|
contentUrl: string;
|
||||||
|
@ -32,11 +39,30 @@ const ContextItem: React.FC<ContextItemProperties> = ({ item }) => {
|
||||||
<div className="text-black dark:text-white">
|
<div className="text-black dark:text-white">
|
||||||
<ReactMarkdown text={item.description} />
|
<ReactMarkdown text={item.description} />
|
||||||
</div>
|
</div>
|
||||||
<a href={item.url} target="_blank" rel="noopener noreferrer" className="text-blue-500 hover:underline">
|
<a
|
||||||
|
href={item.url}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="text-black dark:text-white hover:underline inline-block mt-2"
|
||||||
|
>
|
||||||
Read more
|
Read more
|
||||||
</a>
|
</a>
|
||||||
<div className="text-sm text-gray-500 dark:text-gray-400 mt-2">
|
<div className="mt-2">
|
||||||
{item.provider[0].name} | {new Date(item.datePublished).toLocaleDateString()}
|
<div className="flex items-center text-sm text-gray-700 dark:text-gray-300">
|
||||||
|
{item.provider[0].image && (
|
||||||
|
<Image
|
||||||
|
src={item.provider[0].image.thumbnail.contentUrl}
|
||||||
|
alt={`${item.provider[0].name} logo`}
|
||||||
|
width={16}
|
||||||
|
height={16}
|
||||||
|
className="mr-2"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{item.provider[0].name}
|
||||||
|
</div>
|
||||||
|
<div className="text-xs text-gray-500 dark:text-gray-400 mt-1">
|
||||||
|
{new Date(item.datePublished).toLocaleDateString()}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -19,9 +19,7 @@ const NewsPage = () => {
|
||||||
const fetchNews = async () => {
|
const fetchNews = async () => {
|
||||||
try {
|
try {
|
||||||
console.log("Fetching news...");
|
console.log("Fetching news...");
|
||||||
const response = await fetch(
|
const response = await fetch("/api/news");
|
||||||
"https://raw.githubusercontent.com/newspedia-crew/newspedia-web/intern-change/public/data/index.json",
|
|
||||||
);
|
|
||||||
console.log("Response status:", response.status);
|
console.log("Response status:", response.status);
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(`HTTP error! status: ${response.status}`);
|
throw new Error(`HTTP error! status: ${response.status}`);
|
||||||
|
|
19
ui/lib/constants.ts
Normal file
19
ui/lib/constants.ts
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
export const ENV = {
|
||||||
|
WS_URL: process.env.NEXT_PUBLIC_WS_URL || "ws://localhost:3000",
|
||||||
|
API_URL: process.env.NEXT_PUBLIC_API_URL || "http://localhost:3000/api",
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export type ENV = typeof ENV;
|
||||||
|
|
||||||
|
// Type guard function
|
||||||
|
export function assertEnvVariables(ENV: ENV): asserts ENV is Required<ENV> {
|
||||||
|
const missingVariables = Object.entries(ENV).filter(([_, value]) => value === undefined);
|
||||||
|
if (missingVariables.length > 0) {
|
||||||
|
console.warn(`Warning: Missing environment variables: ${missingVariables.map(([key]) => key).join(", ")}`);
|
||||||
|
console.warn("Using default values for missing variables.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEnvVariables(ENV);
|
||||||
|
|
||||||
|
export const VALIDATED_ENV: Required<ENV> = ENV as Required<ENV>;
|
|
@ -1,9 +0,0 @@
|
||||||
export async function fetchNewsData(id: string) {
|
|
||||||
const response = await fetch(
|
|
||||||
`https://raw.githubusercontent.com/newspedia-crew/newspedia-web/intern-change/public/data/${id}.json`,
|
|
||||||
);
|
|
||||||
if (!response.ok) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return response.json();
|
|
||||||
}
|
|
Loading…
Add table
Reference in a new issue