1+ import React from 'react' ;
2+ import styled from 'styled-components' ;
3+ import {
4+ Card ,
5+ CardContent ,
6+ Typography ,
7+ Button ,
8+ Chip ,
9+ Box ,
10+ } from '@mui/material' ;
11+ import {
12+ SmartToy as AgentIcon ,
13+ Visibility as ViewIcon ,
14+ Link as LinkIcon ,
15+ } from '@mui/icons-material' ;
16+ import { Agent } from '../../../integration/aeamcp-simple' ;
17+
18+ const StyledCard = styled ( Card ) `
19+ background: rgba(255, 255, 255, 0.05) !important;
20+ backdrop-filter: blur(10px);
21+ border: 1px solid rgba(255, 255, 255, 0.1);
22+ transition: all 0.3s ease;
23+ height: 100%;
24+ display: flex;
25+ flex-direction: column;
26+
27+ &:hover {
28+ background: rgba(255, 255, 255, 0.08) !important;
29+ border-color: rgba(139, 92, 246, 0.3);
30+ transform: translateY(-2px);
31+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
32+ }
33+ ` ;
34+
35+ const AgentHeader = styled ( Box ) `
36+ display: flex;
37+ align-items: center;
38+ gap: 1rem;
39+ margin-bottom: 1rem;
40+ ` ;
41+
42+ const AgentIconStyled = styled ( AgentIcon ) `
43+ color: #A78BFA;
44+ font-size: 2rem !important;
45+ ` ;
46+
47+ const CapabilityChip = styled ( Chip ) `
48+ margin: 0.25rem 0.25rem 0 0;
49+ background: rgba(34, 197, 94, 0.1) !important;
50+ border: 1px solid rgba(34, 197, 94, 0.3) !important;
51+ color: #4ADE80 !important;
52+ font-size: 0.75rem;
53+ ` ;
54+
55+ const ActionButton = styled ( Button ) `
56+ margin: 0.25rem !important;
57+ background: rgba(139, 92, 246, 0.1) !important;
58+ border: 1px solid rgba(139, 92, 246, 0.3) !important;
59+ color: #A78BFA !important;
60+
61+ &:hover {
62+ background: rgba(139, 92, 246, 0.2) !important;
63+ border-color: rgba(139, 92, 246, 0.5) !important;
64+ }
65+ ` ;
66+
67+ interface AgentCardProps {
68+ agent : Agent ;
69+ onView : ( agent : Agent ) => void ;
70+ showActions ?: boolean ;
71+ }
72+
73+ export const AgentCard : React . FC < AgentCardProps > = ( {
74+ agent,
75+ onView,
76+ showActions = true
77+ } ) => {
78+ const handleViewClick = ( ) => {
79+ onView ( agent ) ;
80+ } ;
81+
82+ const handleRepositoryClick = ( ) => {
83+ if ( agent . repository ) {
84+ window . open ( agent . repository , '_blank' , 'noopener,noreferrer' ) ;
85+ }
86+ } ;
87+
88+ const handleDocumentationClick = ( ) => {
89+ if ( agent . documentation ) {
90+ window . open ( agent . documentation , '_blank' , 'noopener,noreferrer' ) ;
91+ }
92+ } ;
93+
94+ return (
95+ < StyledCard
96+ role = "article"
97+ aria-labelledby = { `agent-name-${ agent . id } ` }
98+ aria-describedby = { `agent-description-${ agent . id } ` }
99+ >
100+ < CardContent sx = { { flexGrow : 1 , display : 'flex' , flexDirection : 'column' } } >
101+ < AgentHeader >
102+ < AgentIconStyled aria-hidden = "true" />
103+ < Typography
104+ variant = "h6"
105+ id = { `agent-name-${ agent . id } ` }
106+ sx = { {
107+ color : 'white' ,
108+ fontWeight : 600 ,
109+ fontSize : '1.1rem'
110+ } }
111+ >
112+ { agent . name }
113+ </ Typography >
114+ </ AgentHeader >
115+
116+ < Typography
117+ variant = "body2"
118+ id = { `agent-description-${ agent . id } ` }
119+ sx = { {
120+ color : 'rgba(255, 255, 255, 0.7)' ,
121+ marginBottom : 2 ,
122+ flexGrow : 1 ,
123+ display : '-webkit-box' ,
124+ '-webkit-line-clamp' : 3 ,
125+ '-webkit-box-orient' : 'vertical' ,
126+ overflow : 'hidden'
127+ } }
128+ >
129+ { agent . description }
130+ </ Typography >
131+
132+ { agent . capabilities && agent . capabilities . length > 0 && (
133+ < Box
134+ sx = { { marginBottom : 2 } }
135+ role = "list"
136+ aria-label = "Agent capabilities"
137+ >
138+ { agent . capabilities . slice ( 0 , 3 ) . map ( ( capability , index ) => (
139+ < CapabilityChip
140+ key = { index }
141+ label = { capability }
142+ size = "small"
143+ role = "listitem"
144+ aria-label = { `Capability: ${ capability } ` }
145+ />
146+ ) ) }
147+ { agent . capabilities . length > 3 && (
148+ < CapabilityChip
149+ label = { `+${ agent . capabilities . length - 3 } more` }
150+ size = "small"
151+ role = "listitem"
152+ aria-label = { `${ agent . capabilities . length - 3 } more capabilities` }
153+ />
154+ ) }
155+ </ Box >
156+ ) }
157+
158+ { agent . tags && agent . tags . length > 0 && (
159+ < Box
160+ sx = { { marginBottom : 2 } }
161+ role = "list"
162+ aria-label = "Agent tags"
163+ >
164+ { agent . tags . slice ( 0 , 2 ) . map ( ( tag , index ) => (
165+ < Chip
166+ key = { index }
167+ label = { tag }
168+ size = "small"
169+ variant = "outlined"
170+ role = "listitem"
171+ sx = { {
172+ margin : '0.25rem 0.25rem 0 0' ,
173+ borderColor : 'rgba(255, 255, 255, 0.3)' ,
174+ color : 'rgba(255, 255, 255, 0.8)' ,
175+ fontSize : '0.75rem'
176+ } }
177+ />
178+ ) ) }
179+ </ Box >
180+ ) }
181+
182+ { showActions && (
183+ < Box
184+ sx = { {
185+ display : 'flex' ,
186+ gap : 1 ,
187+ flexWrap : 'wrap' ,
188+ marginTop : 'auto'
189+ } }
190+ role = "toolbar"
191+ aria-label = "Agent actions"
192+ >
193+ < ActionButton
194+ size = "small"
195+ startIcon = { < ViewIcon aria-hidden = "true" /> }
196+ onClick = { handleViewClick }
197+ aria-label = { `View details for ${ agent . name } ` }
198+ >
199+ View Details
200+ </ ActionButton >
201+
202+ { agent . repository && (
203+ < ActionButton
204+ size = "small"
205+ startIcon = { < LinkIcon aria-hidden = "true" /> }
206+ onClick = { handleRepositoryClick }
207+ aria-label = { `Open repository for ${ agent . name } in new tab` }
208+ >
209+ Repository
210+ </ ActionButton >
211+ ) }
212+
213+ { agent . documentation && (
214+ < ActionButton
215+ size = "small"
216+ startIcon = { < LinkIcon aria-hidden = "true" /> }
217+ onClick = { handleDocumentationClick }
218+ aria-label = { `Open documentation for ${ agent . name } in new tab` }
219+ >
220+ Docs
221+ </ ActionButton >
222+ ) }
223+ </ Box >
224+ ) }
225+ </ CardContent >
226+ </ StyledCard >
227+ ) ;
228+ } ;
0 commit comments