85 lines
2.6 KiB
TypeScript
85 lines
2.6 KiB
TypeScript
import { Card } from "@heroui/react";
|
|
import { useEffect, useState } from "react";
|
|
|
|
interface GuodegangData {
|
|
name: string;
|
|
content: string;
|
|
}
|
|
|
|
interface Props {
|
|
topic: string;
|
|
}
|
|
|
|
export default function Guodegang({ topic }: Props) {
|
|
const [data, setData] = useState<GuodegangData | null>(null);
|
|
const [loading, setLoading] = useState(true);
|
|
const [error, setError] = useState<string | null>(null);
|
|
|
|
useEffect(() => {
|
|
const fetchData = async () => {
|
|
try {
|
|
const response = await fetch(
|
|
`http://localhost:8080/guodegang/${encodeURIComponent(topic)}`,
|
|
);
|
|
if (!response.ok) {
|
|
throw new Error("API Error");
|
|
}
|
|
const result = await response.json();
|
|
setData(result.message);
|
|
setError(null);
|
|
} catch (error) {
|
|
console.error("Failed to fetch data: ", error);
|
|
setError("Failed to load data. Please try again.");
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
fetchData();
|
|
}, [topic]);
|
|
|
|
if (loading) {
|
|
return (
|
|
<div className="w-full p-4 sm:p-6 md:max-w-2xl lg:max-w-4xl mx-auto">
|
|
<Card className="relative w-full max-w-2xl mx-auto bg-white shadow-xl rounded-2xl overflow-hidden border border-gray-100 p-8">
|
|
<div className="text-center text-gray-600">Loading...</div>
|
|
</Card>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
if (error) {
|
|
return (
|
|
<div className="w-full p-4 sm:p-6 md:max-w-2xl lg:max-w-4xl mx-auto">
|
|
<Card className="relative w-full max-w-2xl mx-auto bg-white shadow-xl rounded-2xl overflow-hidden border border-gray-100 p-8">
|
|
<div className="text-center text-red-600">{error}</div>
|
|
</Card>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div className="w-full p-4 sm:p-6 md:max-w-2xl lg:max-w-4xl mx-auto">
|
|
<Card className="relative w-full max-w-2xl mx-auto bg-white shadow-xl rounded-2xl overflow-hidden border border-gray-100">
|
|
<div className="absolute upper-0 right-0 -mr-2 -mb-2 pointer-events-none select-none">
|
|
<span className="text-[10rem] opacity-80 blur-none">🎤</span>
|
|
</div>
|
|
|
|
<div className="relative z-5">
|
|
<div className="px-6 pt-6 pb-4">
|
|
<Card.Title className="text-2xl font-bold text-gray-800 mb-2">
|
|
{data!.name}
|
|
</Card.Title>
|
|
<div className="h-1 w-20 bg-gradient-to-r from-yellow-500 to-orange-500 rounded"></div>
|
|
</div>
|
|
|
|
<Card.Description className="px-6 pb-6">
|
|
<p className="text-gray-700 leading-relaxed whitespace-pre-line">
|
|
{data!.content}
|
|
</p>
|
|
</Card.Description>
|
|
</div>
|
|
</Card>
|
|
</div>
|
|
);
|
|
}
|