import { useEffect, useState } from "react"; import { useParams, Link } from "react-router-dom"; import Layout from "@/components/Layout"; import SEO from "@/components/SEO"; import { Card, CardContent, CardHeader, CardTitle, CardDescription, } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; import { User, Calendar } from "lucide-react"; import { blogSeedPosts } from "@/data/blogSeed"; import BlogCTASection from "@/components/blog/BlogCTASection"; import FourOhFourPage from "./404"; // API Base URL for fetch requests const API_BASE = import.meta.env.VITE_API_BASE || ""; export default function BlogPost() { const { slug } = useParams<{ slug: string }>(); const [post, setPost] = useState(null); const [loading, setLoading] = useState(true); useEffect(() => { let cancelled = false; (async () => { try { if (!slug) return; // Primary: try server API let res = await fetch( `${API_BASE}/api/blog/${encodeURIComponent(slug)}`, ); let data: any = null; try { // Attempt to parse JSON response from server route if (res.ok) data = await res.json(); } catch (e) { // If server returned HTML (dev server) or invalid JSON, fall back to Supabase REST try { const sbUrl = import.meta.env.VITE_SUPABASE_URL; const sbKey = import.meta.env.VITE_SUPABASE_ANON_KEY; if (sbUrl && sbKey) { const url = `${sbUrl.replace(/\/$/, "")}/rest/v1/blog_posts?slug=eq.${encodeURIComponent( String(slug), )}&select=id,slug,title,excerpt,author,date,read_time,category,image,body_html,published_at`; const sbRes = await fetch(url, { headers: { apikey: sbKey as string, Authorization: `Bearer ${sbKey}`, }, }); if (sbRes.ok) { const arr = await sbRes.json(); data = Array.isArray(arr) && arr.length ? arr[0] : null; } } } catch (err) { console.warn("Supabase fallback fetch failed:", err); } } // If API and Supabase both fail, try seed data if (!data) { const seedPost = blogSeedPosts.find((p) => p.slug === slug); if (seedPost) { data = seedPost; } } if (!cancelled) setPost(data); } catch (e) { console.warn("Blog post fetch failed:", e); } finally { if (!cancelled) setLoading(false); } })(); return () => { cancelled = true; }; }, [slug]); if (loading) return null; if (!post) return ; return ( <>
{post.image && ( {post.title} )} {post.category && ( {post.category} )} {post.title} {post.excerpt && ( {post.excerpt} )}
{post.author && (
{post.author}
)} {post.date && (
{post.date}
)}
{post.body ? (
) : (

{post.excerpt}

)}
Back to Blog
); }