/* * ============================================================================= * VibeQuant (vquant) — AI-Powered Financial Intelligence Platform * ----------------------------------------------------------------------------- * File: client/src/components/explore/ownership-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 { Building2, TrendingUp, TrendingDown, Percent, Calendar } from "lucide-react"; interface InstitutionalHolder { holder: string; shares: number; dateReported: string; change: number; [key: string]: any; } interface OwnershipViewProps { institutionalHolders?: InstitutionalHolder[]; } export function OwnershipView({ institutionalHolders }: OwnershipViewProps) { const formatNumber = (value: number) => { if (!value) return "N/A"; if (value >= 1e9) return `${(value / 1e9).toFixed(2)}B`; if (value >= 1e6) return `${(value / 1e6).toFixed(2)}M`; if (value >= 1e3) return `${(value / 1e3).toFixed(2)}K`; return value.toLocaleString(); }; const formatDate = (dateString: string) => { return new Date(dateString).toLocaleDateString('fr-FR', { year: 'numeric', month: 'long', day: 'numeric' }); }; if (!institutionalHolders || institutionalHolders.length === 0) { return ( Actionnariat Institutionnel

Aucune donnée d'actionnariat disponible

); } const totalShares = institutionalHolders.reduce((sum, holder) => sum + (holder.shares || 0), 0); const holdersWithIncrease = institutionalHolders.filter(h => (h.change || 0) > 0).length; const holdersWithDecrease = institutionalHolders.filter(h => (h.change || 0) < 0).length; return (
{/* Summary Stats */}
Total Institutions
{institutionalHolders.length}
Actions Détenues
{formatNumber(totalShares)}
Augmentations
{holdersWithIncrease}
Diminutions
{holdersWithDecrease}
{/* Detailed Table */} Principaux Actionnaires Institutionnels Détention institutionnelle et changements récents
Rang Institution Actions Détenues Variation % de Variation Date de Rapport {institutionalHolders.map((holder, idx) => { const changeValue = holder.change || 0; const isPositive = changeValue >= 0; const percentChange = holder.shares > 0 ? (changeValue / holder.shares) * 100 : 0; return ( #{idx + 1}
{holder.holder}
{holder.shares > 0 && (
{((holder.shares / totalShares) * 100).toFixed(2)}% du total
)}
{formatNumber(holder.shares)}
{isPositive ? ( ) : ( )} {isPositive ? '+' : ''}{formatNumber(changeValue)}
{isPositive ? '+' : ''}{percentChange.toFixed(2)}%
{formatDate(holder.dateReported)}
); })}
); }