xpeditis2.0/apps/frontend/src/lib/api/blog.ts
David 8877265526 feat(blog): Phase 3 GEO/IA, corbeille, duplication, drag&drop, recadrage
- Bloc GEO/IA (resume IA, FAQ, points cles, entites) + rendu public
  "En bref"/"A retenir"/FAQ + JSON-LD Article & FAQPage.
- Corbeille: soft-delete (deleted_at), filtres Tous/Publies/Brouillons/
  Planifies/Corbeille, restauration + suppression definitive.
- Duplication d'un article (nouveau brouillon, slug unique).
- Drag & drop de l'image de couverture.
- Recadrage auto de la couverture en 16:9 (sharp) via endpoint dedie
  /admin/blog/cover-images.
- Migration AddGeoAndTrashToBlogPosts (ai_summary, faq, key_takeaways,
  ai_entities, deleted_at). Ajout dependance sharp.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 13:44:35 +02:00

65 lines
1.7 KiB
TypeScript

import { get } from './client';
export type BlogPostStatus = 'draft' | 'scheduled' | 'published' | 'archived';
export type BlogPostCategory = 'industry' | 'technology' | 'guides' | 'news';
export interface BlogFaqItem {
question: string;
answer: string;
}
export interface BlogPost {
id: string;
title: string;
slug: string;
excerpt: string;
content: string;
coverImageUrl?: string;
category: BlogPostCategory;
tags: string[];
authorName: string;
status: BlogPostStatus;
isFeatured: boolean;
publishedAt?: string;
metaTitle?: string;
metaDescription?: string;
primaryKeyword?: string;
secondaryKeywords: string[];
// GEO (Generative Engine Optimisation)
aiSummary?: string | null;
faq?: BlogFaqItem[];
keyTakeaways?: string[];
aiEntities?: string[];
createdAt: string;
updatedAt: string;
}
export interface BlogPostListResponse {
posts: BlogPost[];
total: number;
limit: number;
offset: number;
}
export interface BlogPostFilters {
category?: BlogPostCategory;
search?: string;
limit?: number;
offset?: number;
}
export async function getBlogPosts(filters: BlogPostFilters = {}): Promise<BlogPostListResponse> {
const params = new URLSearchParams();
if (filters.category) params.set('category', filters.category);
if (filters.search) params.set('search', filters.search);
if (filters.limit) params.set('limit', String(filters.limit));
if (filters.offset) params.set('offset', String(filters.offset));
const query = params.toString();
return get<BlogPostListResponse>(`/api/v1/blog${query ? `?${query}` : ''}`);
}
export async function getBlogPost(slug: string): Promise<BlogPost> {
return get<BlogPost>(`/api/v1/blog/${slug}`);
}