| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899 |
- import React, { useState, useEffect } from "react";
- import { Link } from "react-router-dom";
- import { useAuth } from "../contexts/AuthContext";
- import { API_BASE } from "../config";
- import Layout, { SkeletonCard } from "./Layout";
- function BlogHome() {
- const [posts, setPosts] = useState([]);
- const [loading, setLoading] = useState(true);
- const [error, setError] = useState(null);
- useEffect(() => {
- async function getTingyun() {
- setLoading(true);
- try {
- const response = await fetch(`${API_BASE}/posts`);
- if (!response.ok)
- throw new Error(
- `Failed to fetch posts: ${response.statusText}`,
- );
- const postsData = await response.json();
- setPosts(postsData);
- } catch (e) {
- console.error("Error fetching posts:", e);
- setError(
- "Failed to load posts. Please check if the backend server is running.",
- );
- } finally {
- setLoading(false);
- }
- }
- getTingyun();
- }, []);
- if (loading) {
- return (
- <Layout>
- <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
- {[1, 2, 3, 4, 5, 6].map((i) => (
- <SkeletonCard key={i} />
- ))}
- </div>
- </Layout>
- );
- }
- if (error) {
- return (
- <Layout>
- <div className="text-center">
- <div className="bg-red-50 border border-red-200 rounded-lg p-6 inline-block">
- <h2 className="text-red-800 font-semibold mb-2">
- Error
- </h2>
- <p className="text-red-600">{error}</p>
- </div>
- </div>
- </Layout>
- );
- }
- return (
- <Layout>
- <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
- {posts.map((post) => (
- <div
- key={post.slug}
- className="group cursor-pointer theme-surface border theme-border rounded-xl hover:border-blue-400 transition-colors duration-200 p-6 flex flex-col justify-between h-full"
- >
- <div>
- <h2 className="text-xl font-semibold theme-text group-hover:theme-primary transition-colors duration-200 mb-2">
- <Link to={`/posts/${post.slug}`}>
- {post.title}
- </Link>
- </h2>
- </div>
- <div className="flex-grow mt-4">
- <div className="theme-text-secondary leading-relaxed">
- {post.description}
- </div>
- </div>
- <div className="mt-4">
- <Link
- to={`/posts/${post.slug}`}
- className="theme-primary font-medium hover:underline focus:outline-none"
- >
- Read more →
- </Link>
- </div>
- </div>
- ))}
- </div>
- </Layout>
- );
- }
- export default BlogHome;
|