diff --git a/src/blog/providers/Article.tsx b/src/blog/providers/Article.tsx index e38a120..0d3f3ab 100644 --- a/src/blog/providers/Article.tsx +++ b/src/blog/providers/Article.tsx @@ -2,18 +2,26 @@ import React, { createContext, useState, useContext, useEffect } from 'react'; import axios from 'axios'; interface Author { + _id?: string | null; + username: string; name: string; + email: string; avatar: string; + is_active: boolean; + created_at?: string; + updated_at?: string; } export interface Article { - id: string; + _id?: string | null; + created_at: string; + updated_at: string; + img: string; tag: string; title: string; description: string; - img: string; + content: string; authors: Author[]; - date?: string; } interface ArticleContextType { @@ -23,7 +31,12 @@ interface ArticleContextType { refreshArticles: () => Promise; } -const Article = createContext(undefined); +const ArticleContext = createContext(undefined); + +// You can configure this through an .env or fallback to localhost +const API_BASE = + import.meta?.env?.VITE_API_BASE_URL || + 'http://localhost:8000'; // Matches your OpenAPI "local development server" export const ArticleProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => { const [articles, setArticles] = useState([]); @@ -32,88 +45,23 @@ export const ArticleProvider: React.FC<{ children: React.ReactNode }> = ({ child const fetchArticles = async () => { try { - // ✅ Use static defaults first - const defaults = [ - { - img: 'https://picsum.photos/800/450?random=1', - tag: 'Engineering', - title: 'Revolutionizing software development with cutting-edge tools', - description: - 'Our latest engineering tools are designed to streamline workflows and boost productivity. Discover how these innovations are transforming the software development landscape.', - content: - 'Our latest engineering tools are designed to streamline workflows and boost productivity. Discover how these innovations are transforming the software development landscape.', - authors: [ - { name: 'Remy Sharp', avatar: '/static/images/avatar/1.jpg' }, - { name: 'Travis Howard', avatar: '/static/images/avatar/2.jpg' }, - ], - }, - { - img: 'https://picsum.photos/800/450?random=2', - tag: 'Product', - title: 'Innovative product features that drive success', - description: - 'Explore the key features of our latest product release that are helping businesses achieve their goals. From user-friendly interfaces to robust functionality, learn why our product stands out.', - content: - 'Explore the key features of our latest product release that are helping businesses achieve their goals. From user-friendly interfaces to robust functionality, learn why our product stands out.', - authors: [{ name: 'Erica Johns', avatar: '/static/images/avatar/6.jpg' }], - }, - { - img: 'https://picsum.photos/800/450?random=3', - tag: 'Design', - title: 'Designing for the future: trends and insights', - description: - 'Stay ahead of the curve with the latest design trends and insights. Our design team shares their expertise on creating intuitive and visually stunning user experiences.', - content: - 'Stay ahead of the curve with the latest design trends and insights. Our design team shares their expertise on creating intuitive and visually stunning user experiences.', - authors: [{ name: 'Kate Morrison', avatar: '/static/images/avatar/7.jpg' }], - }, - { - img: 'https://picsum.photos/800/450?random=4', - tag: 'Company', - title: "Our company's journey: milestones and achievements", - description: - "Take a look at our company's journey and the milestones we've achieved along the way. From humble beginnings to industry leader, discover our story of growth and success.", - content: - "Take a look at our company's journey and the milestones we've achieved along the way. From humble beginnings to industry leader, discover our story of growth and success.", - authors: [{ name: 'Cindy Baker', avatar: '/static/images/avatar/3.jpg' }], - }, - { - img: 'https://picsum.photos/800/450?random=45', - tag: 'Engineering', - title: 'Pioneering sustainable engineering solutions', - description: - "Learn about our commitment to sustainability and the innovative engineering solutions we're implementing to create a greener future. Discover the impact of our eco-friendly initiatives.", - content: - "Learn about our commitment to sustainability and the innovative engineering solutions we're implementing to create a greener future. Discover the impact of our eco-friendly initiatives.", - authors: [ - { name: 'Agnes Walker', avatar: '/static/images/avatar/4.jpg' }, - { name: 'Trevor Henderson', avatar: '/static/images/avatar/5.jpg' }, - ], - }, - { - img: 'https://picsum.photos/800/450?random=6', - tag: 'Product', - title: 'Maximizing efficiency with our latest product updates', - description: - 'Our recent product updates are designed to help you maximize efficiency and achieve more. Get a detailed overview of the new features and improvements that can elevate your workflow.', - content: - 'Our recent product updates are designed to help you maximize efficiency and achieve more. Get a detailed overview of the new features and improvements that can elevate your workflow.', - authors: [{ name: 'Travis Howard', avatar: '/static/images/avatar/2.jpg' }], - }, - ]; - - // ✅ For now: only use defaults - // @ts-ignore - setArticles(defaults); - setLoading(false); - - // 🔜 Optional: uncomment this to fetch from API when backend is ready - /* setLoading(true); - const res = await axios.get('/articles'); - setArticles(res.data); - */ + setError(null); + + // ✅ Use correct full endpoint from OpenAPI spec + const res = await axios.get(`${API_BASE}/articles`, { + params: { skip: 0, limit: 10 }, + }); + + // ✅ Normalize if backend sends _id instead of id + const formatted = res.data.map((a) => ({ + ...a, + id: a._id || undefined, + })); + + setArticles(formatted); } catch (err: any) { + console.error('Failed to fetch articles:', err); setError(err.message || 'Failed to fetch articles'); } finally { setLoading(false); @@ -125,14 +73,14 @@ export const ArticleProvider: React.FC<{ children: React.ReactNode }> = ({ child }, []); return ( - + {children} - + ); }; export const useArticles = (): ArticleContextType => { - const ctx = useContext(Article); + const ctx = useContext(ArticleContext); if (!ctx) throw new Error('useArticles must be used inside ArticleProvider'); return ctx; };