saas-veille / lib /content-utils.ts
PrestaGhis's picture
Update lib/content-utils.ts
17885bc verified
/**
* Extrait un label textuel d'un item qui peut être soit une string,
* soit un objet avec différentes propriétés possibles selon le champ (LSI, Gap, PAA).
*/
export function extractLabel(item: any): string {
if (typeof item === 'string') return item;
if (!item) return '';
// Ordre de priorité des propriétés communes remontées par les différents moteurs IA
return (
item.keyword ||
item.topic ||
item.question ||
item.text ||
item.label ||
item.name ||
item.title ||
''
);
}
/**
* Version plus spécifique pour les clusters sémantiques qui peuvent avoir du volume.
*/
export function extractKeyword(item: any): { keyword: string; volume: number | null } {
if (typeof item === 'string') return { keyword: item, volume: null };
if (!item) return { keyword: '', volume: null };
// Extraction du mot-clé
const keyword = item.keyword || item.topic || item.text || item.label || item.word || '';
// Extraction du volume (robuste aux valeurs 0 et aux différents noms de champs)
let volume: any = null;
const volFields = ['volume', 'vol', 'search_volume', 'monthly_queries', 'avg_ms', 'ms'];
for (const field of volFields) {
if (item[field] !== undefined && item[field] !== null) {
volume = item[field];
break;
}
}
// Support pour les objets imbriqués 'metrics' (Haloscan)
if ((volume === null || volume === undefined) && item.metrics && typeof item.metrics === 'object') {
for (const field of volFields) {
if (item.metrics[field] !== undefined && item.metrics[field] !== null) {
volume = item.metrics[field];
break;
}
}
}
return {
keyword,
volume: (volume !== null && volume !== undefined && volume !== '') ? Number(volume) : null
};
}
/**
* Formate un nombre de volume pour l'affichage (ex: 1200 -> 1.2k)
*/
export function formatVolume(v: number | string | null | undefined): string | null {
if (v === null || v === undefined || v === '') return null;
// On traite "N/A" comme null pour que le composant UI affiche son fallback (ex: '< 10')
if (v === 'N/A') return null;
// Si c'est une chaîne non numérique (ex: "E:ERR"), on l'affiche telle quelle
if (typeof v === 'string' && isNaN(Number(v))) {
return v;
}
const num = typeof v === 'string' ? parseInt(v, 10) : v;
if (isNaN(num)) return null;
if (num >= 1000) return (num / 1000).toFixed(1) + 'k';
return num.toString();
}