generated from lucien/actix-react-template
48 lines
1.9 KiB
TypeScript
48 lines
1.9 KiB
TypeScript
import { useEffect, useState } from "react";
|
|
import ArticleCard from "./ArticleCard";
|
|
import { ArticlePreview } from "../types";
|
|
|
|
export default function ArticlesSection() {
|
|
|
|
const [articlePreviews, setArticlePreviews] = useState<ArticlePreview[]>([]);
|
|
const [loading, setLoading] = useState<boolean>(true);
|
|
const [error, setError] = useState<string | null>(null);
|
|
|
|
useEffect(() => {
|
|
fetch('/api/articles')
|
|
.then(response => response.json())
|
|
.then((data: ArticlePreview[]) => setArticlePreviews(data))
|
|
.catch(_ => setError('Failed to fetch articles'))
|
|
.finally(() => setLoading(false));
|
|
}, []);
|
|
|
|
return (
|
|
<div className="row" style={{
|
|
display: 'flex',
|
|
flexWrap: 'wrap',
|
|
justifyContent: 'space-around',
|
|
backgroundColor: 'var(--color-verydarkblue)',
|
|
flex: 1,
|
|
}}>
|
|
<h1 style={{
|
|
color: 'var(--color-yellow)',
|
|
fontFamily: '"Haas Grot Text R Web", "Helvetica Neue", Helvetica, Arial, sans-serif',
|
|
fontSize: '32px',
|
|
fontWeight: '500',
|
|
lineHeight: '30px',
|
|
margin: '20px',
|
|
padding: '10px',
|
|
paddingBottom: '0',
|
|
marginBottom: '10px',
|
|
textAlign: 'center',
|
|
width: '100%',
|
|
}}>Articles</h1>
|
|
{articlePreviews.map(articlePreview => (
|
|
<ArticleCard key={articlePreview.id} articlePreview={articlePreview} />
|
|
))}
|
|
{!loading && !error && articlePreviews.length === 0 && <p style={{color: "var(--color-lightblue)", fontSize: 22}}>No articles found</p>}
|
|
{loading && <p style={{color: "var(--color-lightblue)", fontSize: 22}}>Loading...</p>}
|
|
{error && <p style={{color: "var(--color-lightblue)", fontSize: 22}}>{error}</p>}
|
|
</div>
|
|
)
|
|
}
|