Files
bakery-ia/frontend/src/components/subscription/PricingFeatureCategory.tsx

122 lines
3.5 KiB
TypeScript
Raw Normal View History

2025-11-15 15:20:10 +01:00
import React, { useState } from 'react';
import { useTranslation } from 'react-i18next';
interface Feature {
key: string;
translation_key: string;
tooltip_key?: string;
category: string;
}
interface Category {
icon: string;
translation_key: string;
}
interface PricingFeatureCategoryProps {
categoryKey: string;
category: Category;
features: Feature[];
className?: string;
}
/**
* PricingFeatureCategory - Displays a collapsible category of features
* Groups related features with icons for better organization
*/
export const PricingFeatureCategory: React.FC<PricingFeatureCategoryProps> = ({
categoryKey,
category,
features,
className = '',
}) => {
const [isExpanded, setIsExpanded] = useState(false);
const { t } = useTranslation('subscription');
if (features.length === 0) {
return null;
}
const categoryName = t(category.translation_key);
return (
<div className={`border-b border-gray-200 last:border-b-0 ${className}`}>
<button
onClick={() => setIsExpanded(!isExpanded)}
className="w-full flex items-center justify-between py-3 px-4 hover:bg-gray-50 transition-colors"
aria-expanded={isExpanded}
aria-controls={`category-${categoryKey}`}
>
<div className="flex items-center gap-2">
<span className="text-xl" role="img" aria-label={categoryName}>
{category.icon}
</span>
<span className="font-semibold text-gray-800 text-sm">
{categoryName}
</span>
<span className="text-xs text-gray-500 bg-gray-100 px-2 py-0.5 rounded-full">
{features.length}
</span>
</div>
<svg
className={`w-5 h-5 text-gray-400 transition-transform ${
isExpanded ? 'rotate-180' : ''
}`}
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M19 9l-7 7-7-7"
/>
</svg>
</button>
{isExpanded && (
<div
id={`category-${categoryKey}`}
className="px-4 pb-3 space-y-2"
>
{features.map((feature) => {
const featureName = t(feature.translation_key);
const tooltip = feature.tooltip_key ? t(feature.tooltip_key) : undefined;
return (
<div
key={feature.key}
className="flex items-start gap-2 text-sm group"
title={tooltip}
>
<svg
className="w-4 h-4 text-green-500 flex-shrink-0 mt-0.5"
fill="currentColor"
viewBox="0 0 20 20"
>
<path
fillRule="evenodd"
d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z"
clipRule="evenodd"
/>
</svg>
<span className="text-gray-700 flex-1">
{featureName}
{tooltip && (
<span className="ml-1 text-gray-400 opacity-0 group-hover:opacity-100 transition-opacity">
</span>
)}
</span>
</div>
);
})}
</div>
)}
</div>
);
};
export default PricingFeatureCategory;