import React from 'react'; import { useTranslation } from 'react-i18next'; import { MarketServer } from '@/types'; interface MarketServerCardProps { server: MarketServer; onClick: (server: MarketServer) => void; } const MarketServerCard: React.FC = ({ server, onClick }) => { const { t } = useTranslation(); // Intelligently calculate how many tags to display to ensure they fit in a single line const getTagsToDisplay = () => { if (!server.tags || server.tags.length === 0) { return { tagsToShow: [], hasMore: false, moreCount: 0 }; } // Estimate available width in the card (in characters) const estimatedAvailableWidth = 28; // Estimated number of characters that can fit in one line // Calculate the character space needed for tags and plus sign (including # and spacing) const calculateTagWidth = (tag: string) => tag.length + 3; // +3 for # and spacing // Loop to determine the maximum number of tags that can be displayed let totalWidth = 0; let i = 0; // First, sort tags by length to prioritize displaying shorter tags const sortedTags = [...server.tags].sort((a, b) => a.length - b.length); // Calculate how many tags can fit for (i = 0; i < sortedTags.length; i++) { const tagWidth = calculateTagWidth(sortedTags[i]); // If this tag would make the total width exceed available width, stop adding if (totalWidth + tagWidth > estimatedAvailableWidth) { break; } totalWidth += tagWidth; // If this is the last tag but there's still space, no need to show "more" if (i === sortedTags.length - 1) { return { tagsToShow: sortedTags, hasMore: false, moreCount: 0 }; } } // If there's not enough space to display any tags, show at least one if (i === 0 && sortedTags.length > 0) { i = 1; } // Calculate space needed for the "more" tag const moreCount = sortedTags.length - i; const moreTagWidth = 3 + String(moreCount).length + t('market.moreTags').length; // If there's enough remaining space to display the "more" tag if (totalWidth + moreTagWidth <= estimatedAvailableWidth || i < 1) { return { tagsToShow: sortedTags.slice(0, i), hasMore: true, moreCount }; } // If there's not enough space for even the "more" tag, reduce one tag to make room return { tagsToShow: sortedTags.slice(0, Math.max(1, i - 1)), hasMore: true, moreCount: moreCount + 1 }; }; const { tagsToShow, hasMore, moreCount } = getTagsToDisplay(); return (
onClick(server)} >

{server.display_name}

{server.is_official && ( {t('market.official')} )}

{server.description}

{/* Categories */}
{server.categories?.length > 0 ? ( server.categories.map((category, index) => ( {category} )) ) : ( - )}
{/* Tags */}
{server.tags?.length > 0 ? (
{tagsToShow.map((tag, index) => ( #{tag} ))} {hasMore && ( +{moreCount} {t('market.moreTags')} )}
) : ( - )}
{t('market.by')} {server.author?.name || t('market.unknown')}
{server.tools?.length || 0} {t('market.tools')}
); }; export default MarketServerCard;