Files
bakery-ia/frontend/src/components/subscription/PricingFeatureCategory.tsx
2025-11-15 15:20:10 +01:00

122 lines
3.5 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;