1+
12'use client' ;
23
3- import { Card , CardHeader , CardTitle , CardDescription , CardContent } from "@/components/ui/card" ;
4+ import { Card , CardHeader , CardTitle , CardDescription , CardContent , CardFooter } from "@/components/ui/card" ;
45import { Table , TableBody , TableCell , TableHead , TableHeader , TableRow } from "@/components/ui/table" ;
56import { Badge } from "@/components/ui/badge" ;
67import { CreateCompanyDialog } from '@/components/create-company-dialog' ;
@@ -9,7 +10,8 @@ import Link from 'next/link';
910import { InvestDialog } from '@/components/invest-dialog' ;
1011import type { CompanyWithDetails , ManagedCompany , InvestedCompany , OtherCompany } from '@/lib/actions/companies' ;
1112import { SellSharesDialog } from '@/components/sell-shares-dialog' ;
12-
13+ import { Area , AreaChart , Tooltip } from 'recharts' ;
14+ import { ChartContainer , ChartTooltipContent } from "@/components/ui/chart" ;
1315
1416function CompanyTableRow ( { company, type } : { company : any , type : 'managed' | 'invested' | 'other' } ) {
1517 const hasShares = company . sharesHeld > 0 ;
@@ -42,41 +44,10 @@ function CompanyTableRow({ company, type }: { company: any, type: 'managed' | 'i
4244 < Button asChild variant = "outline" size = "sm" >
4345 < Link href = { `/companies/${ company . id } ` } > Détails</ Link >
4446 </ Button >
45-
46- { company . isListed ? (
47- < >
48- < InvestDialog company = { company as CompanyWithDetails } isListed >
49- < Button size = "sm" > Acheter</ Button >
50- </ InvestDialog >
51- { hasShares && (
52- < SellSharesDialog
53- companyId = { company . id }
54- companyName = { company . name }
55- sharePrice = { company . sharePrice }
56- sharesHeld = { company . sharesHeld }
57- isListed
58- >
59- < Button size = "sm" variant = "destructive" > Vendre</ Button >
60- </ SellSharesDialog >
61- ) }
62- </ >
63- ) : ( // Not listed
64- < >
65- { hasShares && (
66- < SellSharesDialog
67- companyId = { company . id }
68- companyName = { company . name }
69- sharePrice = { company . sharePrice }
70- sharesHeld = { company . sharesHeld }
71- >
72- < Button size = "sm" variant = "destructive" > Vendre</ Button >
73- </ SellSharesDialog >
74- ) }
75- < InvestDialog company = { company as CompanyWithDetails } >
76- < Button size = "sm" > Investir</ Button >
77- </ InvestDialog >
78- </ >
79- ) }
47+ { /* Note: Investing in private companies from this table */ }
48+ < InvestDialog company = { company as CompanyWithDetails } >
49+ < Button size = "sm" > Investir</ Button >
50+ </ InvestDialog >
8051 </ TableCell >
8152 </ TableRow >
8253 ) ;
@@ -86,8 +57,8 @@ function CompanyTable({ title, description, companies, type }: { title: string,
8657 const headers = {
8758 managed : [ "Entreprise" , "Mon Rôle" , "Mes Parts" , "Valeur des Parts" , "" ] ,
8859 invested : [ "Entreprise" , "Parts Détenues" , "Valeur des Parts" , "" ] ,
89- other : [ "Entreprise" , "Trésorerie" , "Cap. Boursière" , "" ]
90- }
60+ other : [ "Entreprise" , "Trésorerie" , "Cap. Boursière" , "" ] ,
61+ } ;
9162
9263 return (
9364 < Card >
@@ -110,15 +81,95 @@ function CompanyTable({ title, description, companies, type }: { title: string,
11081 ) : (
11182 < TableRow >
11283 < TableCell colSpan = { headers [ type ] . length } className = "h-24 text-center text-muted-foreground" >
113- { type === 'managed' ? "Vous ne gérez aucune entreprise." : type === 'invested' ? "Vous n'avez investi dans aucune entreprise." : "Aucune autre entreprise disponible." }
84+ { type === 'managed' ? "Vous ne gérez aucune entreprise." : type === 'invested' ? "Vous n'avez investi dans aucune entreprise." : "Aucune entreprise privée disponible." }
11485 </ TableCell >
11586 </ TableRow >
11687 ) }
11788 </ TableBody >
11889 </ Table >
11990 </ CardContent >
12091 </ Card >
121- )
92+ ) ;
93+ }
94+
95+
96+ function StockExchangeCard ( { company } : { company : OtherCompany } ) {
97+ const changeIsPositive = company . change24h . startsWith ( '+' ) ;
98+ const chartConfig = {
99+ price : {
100+ label : 'Prix' ,
101+ color : changeIsPositive ? 'hsl(var(--chart-1))' : 'hsl(var(--destructive))' ,
102+ } ,
103+ } ;
104+
105+ return (
106+ < Card className = "flex flex-col" >
107+ < CardHeader >
108+ < div className = "flex items-start justify-between" >
109+ < div >
110+ < CardTitle className = "text-base" > { company . name } ({ company . ticker } )</ CardTitle >
111+ < CardDescription > { company . industry } </ CardDescription >
112+ </ div >
113+ < Badge variant = "secondary" > En Bourse</ Badge >
114+ </ div >
115+ </ CardHeader >
116+ < CardContent className = "flex-grow space-y-4" >
117+ < div className = "h-[100px] w-full -translate-x-4" >
118+ < ChartContainer config = { chartConfig } >
119+ < AreaChart
120+ accessibilityLayer
121+ data = { company . historicalData }
122+ margin = { { top : 5 , right : 10 , left : 10 , bottom : 0 } }
123+ >
124+ < defs >
125+ < linearGradient id = { `fill-${ company . ticker } ` } x1 = "0" y1 = "0" x2 = "0" y2 = "1" >
126+ < stop offset = "5%" stopColor = "var(--color-price)" stopOpacity = { 0.8 } />
127+ < stop offset = "95%" stopColor = "var(--color-price)" stopOpacity = { 0.1 } />
128+ </ linearGradient >
129+ </ defs >
130+ < Tooltip
131+ cursor = { false }
132+ content = { < ChartTooltipContent indicator = "dot" hideLabel /> }
133+ />
134+ < Area
135+ dataKey = "price"
136+ type = "natural"
137+ fill = { `url(#fill-${ company . ticker } )` }
138+ strokeWidth = { 2 }
139+ stroke = "var(--color-price)"
140+ stackId = "a"
141+ />
142+ </ AreaChart >
143+ </ ChartContainer >
144+ </ div >
145+ < div >
146+ < div className = "text-xl font-bold" > ${ company . sharePrice . toFixed ( 4 ) } </ div >
147+ < p className = { `text-xs ${ changeIsPositive ? 'text-green-500' : 'text-red-500' } ` } >
148+ { company . change24h } (24h)
149+ </ p >
150+ </ div >
151+ </ CardContent >
152+ < CardFooter className = "flex justify-end gap-2" >
153+ < Button asChild variant = "outline" size = "sm" >
154+ < Link href = { `/companies/${ company . id } ` } > Détails</ Link >
155+ </ Button >
156+ < InvestDialog company = { company as any } isListed >
157+ < Button size = "sm" > Acheter</ Button >
158+ </ InvestDialog >
159+ { company . sharesHeld > 0 && (
160+ < SellSharesDialog
161+ companyId = { company . id }
162+ companyName = { company . name }
163+ sharePrice = { company . sharePrice }
164+ sharesHeld = { company . sharesHeld }
165+ isListed
166+ >
167+ < Button size = "sm" variant = "secondary" > Vendre</ Button >
168+ </ SellSharesDialog >
169+ ) }
170+ </ CardFooter >
171+ </ Card >
172+ ) ;
122173}
123174
124175interface CompaniesClientPageProps {
@@ -128,7 +179,9 @@ interface CompaniesClientPageProps {
128179}
129180
130181export function CompaniesClientPage ( { managedCompanies, investedCompanies, otherCompanies } : CompaniesClientPageProps ) {
131-
182+ const listedCompanies = otherCompanies . filter ( c => c . isListed ) ;
183+ const privateCompanies = otherCompanies . filter ( c => ! c . isListed ) ;
184+
132185 return (
133186 < div className = "space-y-6" >
134187 < div className = "flex items-center justify-between" >
@@ -157,12 +210,28 @@ export function CompaniesClientPage({ managedCompanies, investedCompanies, other
157210 />
158211 ) }
159212
160- < CompanyTable
161- title = "Bourse des Entreprises"
162- description = "Toutes les entreprises disponibles à l'investissement ou au trading."
163- companies = { otherCompanies }
164- type = "other"
165- />
213+ < Card >
214+ < CardHeader >
215+ < CardTitle > Bourse des Entreprises</ CardTitle >
216+ < CardDescription > Entreprises cotées disponibles pour le trading public.</ CardDescription >
217+ </ CardHeader >
218+ < CardContent className = "grid gap-6 md:grid-cols-2 lg:grid-cols-3" >
219+ { listedCompanies . length > 0 ? (
220+ listedCompanies . map ( ( company ) => < StockExchangeCard key = { company . id } company = { company } /> )
221+ ) : (
222+ < p className = "col-span-full py-12 text-center text-muted-foreground" > Aucune entreprise n'est actuellement cotée en bourse.</ p >
223+ ) }
224+ </ CardContent >
225+ </ Card >
226+
227+ { privateCompanies . length > 0 && (
228+ < CompanyTable
229+ title = "Autres Entreprises Privées"
230+ description = "Entreprises non cotées dans lesquelles vous pouvez réaliser un investissement initial."
231+ companies = { privateCompanies }
232+ type = "other"
233+ />
234+ ) }
166235 </ div >
167236 ) ;
168237}
0 commit comments