import { useTranslation } from '../../i18n' import type { NormalizedSkill } from '../../types/market' import { InstallStateBadge } from './InstallStateBadge' import { SecurityBadge } from './SecurityBadge' import { SkillAvatar } from './SkillAvatar' function formatCount(value: number): string { if (value >= 1_000_000) return `${(value / 1_000_000).toFixed(1)}M` if (value >= 1_000) return `${(value / 1_000).toFixed(1)}k` return String(value) } const MAX_VISIBLE_TAGS = 3 export function SkillCard({ skill, onOpen, onInstall, installing, }: { skill: NormalizedSkill onOpen: (id: string) => void onInstall?: (id: string) => void installing?: boolean }) { const t = useTranslation() const extraTags = Math.max(0, skill.tags.length - MAX_VISIBLE_TAGS) const showInstallButton = Boolean(onInstall) && skill.installState === 'installable' return (
onOpen(skill.id)} onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault() onOpen(skill.id) } }} >
{skill.name} {skill.version && ( v{skill.version} )}
{t(`market.source.${skill.source}`)} {skill.author.handle && ( {t('market.card.by', { author: skill.author.displayName || skill.author.handle })} )}

{skill.summary || t('market.detail.noDescription')}

{skill.tags.length > 0 && (
{skill.tags.slice(0, MAX_VISIBLE_TAGS).map((tag) => ( {tag} ))} {extraTags > 0 && ( {t('market.card.moreTags', { count: String(extraTags) })} )}
)}
{/* The quick-install button already communicates "installable" — skip the badge when the button renders. */} {!(skill.installState === 'installable' && showInstallButton) && ( )}
download {formatCount(skill.stats.downloads)} {typeof skill.stats.stars === 'number' && skill.stats.stars > 0 && ( star {formatCount(skill.stats.stars)} )} {showInstallButton && ( )}
) }