- 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>
65 lines
1.7 KiB
TypeScript
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}`);
|
|
}
|