/* * ============================================================================= * VibeQuant (vquant) — AI-Powered Financial Intelligence Platform * ----------------------------------------------------------------------------- * File: client/src/components/explore/analyst-view.tsx * * Author: Simon-Pierre Boucher * Contact: contact@spboucher.ai * Website: https://www.spboucher.ai * Demo: https://www.vquant.ai * License: MIT (see LICENSE) * * Copyright © 2026 Simon-Pierre Boucher. All rights reserved. * ============================================================================= */ import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"; import { TrendingUp, TrendingDown, Award, Target, DollarSign, Users } from "lucide-react"; interface AnalystEstimate { date: string; symbol: string; estimatedRevenueAvg: number; estimatedRevenueLow: number; estimatedRevenueHigh: number; estimatedEbitdaAvg: number; estimatedEbitdaLow: number; estimatedEbitdaHigh: number; estimatedEbitAvg: number; estimatedEbitLow: number; estimatedEbitHigh: number; estimatedNetIncomeAvg: number; estimatedNetIncomeLow: number; estimatedNetIncomeHigh: number; estimatedSgaExpenseAvg: number; estimatedSgaExpenseLow: number; estimatedSgaExpenseHigh: number; estimatedEpsAvg: number; estimatedEpsLow: number; estimatedEpsHigh: number; numberAnalystEstimatedRevenue: number; numberAnalystsEstimatedEps: number; } interface DividendData { date: string; label: string; adjDividend: number; dividend: number; recordDate: string; paymentDate: string; declarationDate: string; } interface AnalystViewProps { analystEstimates?: AnalystEstimate[]; dividends?: DividendData[]; } export function AnalystView({ analystEstimates, dividends }: AnalystViewProps) { const formatCurrency = (value: number) => { if (!value) return "N/A"; const absValue = Math.abs(value); if (absValue >= 1e12) return `$${(value / 1e12).toFixed(2)}T`; if (absValue >= 1e9) return `$${(value / 1e9).toFixed(2)}B`; if (absValue >= 1e6) return `$${(value / 1e6).toFixed(2)}M`; if (absValue >= 1e3) return `$${(value / 1e3).toFixed(2)}K`; return `$${value.toFixed(2)}`; }; const formatDate = (dateString: string) => { return new Date(dateString).toLocaleDateString('fr-FR', { year: 'numeric', month: 'short', day: 'numeric' }); }; const estimateRows = [ { label: "Revenu", avgKey: "estimatedRevenueAvg", lowKey: "estimatedRevenueLow", highKey: "estimatedRevenueHigh", analystKey: "numberAnalystEstimatedRevenue", isCurrency: true }, { label: "EBITDA", avgKey: "estimatedEbitdaAvg", lowKey: "estimatedEbitdaLow", highKey: "estimatedEbitdaHigh", isCurrency: true }, { label: "EBIT", avgKey: "estimatedEbitAvg", lowKey: "estimatedEbitLow", highKey: "estimatedEbitHigh", isCurrency: true }, { label: "Revenu Net", avgKey: "estimatedNetIncomeAvg", lowKey: "estimatedNetIncomeLow", highKey: "estimatedNetIncomeHigh", isCurrency: true }, { label: "Dépenses SG&A", avgKey: "estimatedSgaExpenseAvg", lowKey: "estimatedSgaExpenseLow", highKey: "estimatedSgaExpenseHigh", isCurrency: true }, { label: "BPA", avgKey: "estimatedEpsAvg", lowKey: "estimatedEpsLow", highKey: "estimatedEpsHigh", analystKey: "numberAnalystsEstimatedEps", isEPS: true }, ]; return (
{/* Analyst Estimates */} {analystEstimates && analystEstimates.length > 0 ? (
Estimations des Analystes Prévisions consensuelles et fourchettes d'estimations
{analystEstimates[0]?.numberAnalystsEstimatedEps || 'N/A'} analystes
Métrique {analystEstimates.slice(0, 4).map((item, idx) => (
{formatDate(item.date)}
{item.numberAnalystEstimatedRevenue > 0 && (
{item.numberAnalystEstimatedRevenue} analystes
)}
))}
{estimateRows.map((row, rowIdx) => (
{row.label}
{analystEstimates.slice(0, 4).map((item, idx) => { const avg = item[row.avgKey]; const low = item[row.lowKey]; const high = item[row.highKey]; return (
{row.isCurrency ? formatCurrency(avg) : row.isEPS ? `$${avg?.toFixed(2) || 'N/A'}` : avg || 'N/A'}
Fourchette:
{row.isCurrency ? formatCurrency(low) : row.isEPS ? `$${low?.toFixed(2) || 'N/A'}` : low || 'N/A'} - {row.isCurrency ? formatCurrency(high) : row.isEPS ? `$${high?.toFixed(2) || 'N/A'}` : high || 'N/A'}
); })}
))}
) : ( Estimations des Analystes

Aucune estimation d'analyste disponible

)} {/* Dividend History */} {dividends && dividends.length > 0 ? ( Historique des Dividendes Paiements de dividendes et dates importantes
Date Ex-Dividend Libellé Dividende Dividende Ajusté Date d'Enregistrement Date de Paiement Date de Déclaration {dividends.slice(0, 20).map((dividend, idx) => ( {formatDate(dividend.date)} {dividend.label} ${dividend.dividend?.toFixed(4)} ${dividend.adjDividend?.toFixed(4)} {dividend.recordDate ? formatDate(dividend.recordDate) : 'N/A'} {dividend.paymentDate ? formatDate(dividend.paymentDate) : 'N/A'} {dividend.declarationDate ? formatDate(dividend.declarationDate) : 'N/A'} ))}
{dividends.length > 0 && (
Total Paiements
{dividends.length}
Dernier Dividende
${dividends[0]?.dividend?.toFixed(4)}
Dividende Annuel (TTM)
${dividends.slice(0, 4).reduce((sum, d) => sum + (d.dividend || 0), 0).toFixed(4)}
)}
) : ( Historique des Dividendes

Cette entreprise ne verse pas de dividendes

)}
); }