Create the frontend receipes page to use real API 2

This commit is contained in:
Urtzi Alfaro
2025-09-20 08:24:03 +02:00
parent d18c64ce6e
commit 66ef2121a1
6 changed files with 177 additions and 82 deletions

View File

@@ -0,0 +1,122 @@
import React from 'react';
import { Card } from '../Card';
export interface TabItem {
id: string;
label: string;
disabled?: boolean;
}
export interface TabsProps {
items: TabItem[];
activeTab: string;
onTabChange: (tabId: string) => void;
variant?: 'default' | 'pills' | 'underline';
size?: 'sm' | 'md' | 'lg';
fullWidth?: boolean;
className?: string;
}
const Tabs: React.FC<TabsProps> = ({
items,
activeTab,
onTabChange,
variant = 'pills',
size = 'md',
fullWidth = false,
className = ''
}) => {
// Size classes
const sizeClasses = {
sm: 'px-2 py-1.5 text-xs',
md: 'px-3 sm:px-4 py-3 sm:py-2 text-sm',
lg: 'px-4 sm:px-6 py-4 sm:py-3 text-base'
};
// Variant styles
const getVariantClasses = (isActive: boolean, isDisabled: boolean) => {
if (isDisabled) {
return 'text-[var(--text-tertiary)] cursor-not-allowed opacity-50';
}
switch (variant) {
case 'pills':
return isActive
? 'bg-[var(--color-primary)] text-white'
: 'text-[var(--text-secondary)] hover:text-[var(--text-primary)] hover:bg-[var(--bg-secondary)]';
case 'underline':
return isActive
? 'text-[var(--color-primary)] border-b-2 border-[var(--color-primary)]'
: 'text-[var(--text-secondary)] hover:text-[var(--text-primary)] border-b-2 border-transparent';
default:
return isActive
? 'bg-[var(--color-primary)] text-white'
: 'text-[var(--text-secondary)] hover:text-[var(--text-primary)] hover:bg-[var(--bg-secondary)]';
}
};
const baseButtonClasses = `
font-medium transition-colors
${fullWidth ? 'flex-1' : 'sm:flex-none'}
${variant === 'pills' ? 'rounded-md' : ''}
${sizeClasses[size]}
`.trim();
if (variant === 'underline') {
return (
<div className={`border-b border-[var(--border-primary)] ${className}`}>
<nav className="flex">
{items.map((item) => {
const isActive = activeTab === item.id;
const isDisabled = item.disabled || false;
return (
<button
key={item.id}
onClick={() => !isDisabled && onTabChange(item.id)}
disabled={isDisabled}
className={`
${baseButtonClasses}
${getVariantClasses(isActive, isDisabled)}
`}
type="button"
>
{item.label}
</button>
);
})}
</nav>
</div>
);
}
return (
<Card className={`p-1 ${className}`}>
<div className="flex space-x-1">
{items.map((item) => {
const isActive = activeTab === item.id;
const isDisabled = item.disabled || false;
return (
<button
key={item.id}
onClick={() => !isDisabled && onTabChange(item.id)}
disabled={isDisabled}
className={`
${baseButtonClasses}
${getVariantClasses(isActive, isDisabled)}
`}
type="button"
>
{item.label}
</button>
);
})}
</div>
</Card>
);
};
export default Tabs;

View File

@@ -0,0 +1,2 @@
export { default as Tabs } from './Tabs';
export type { TabsProps, TabItem } from './Tabs';

View File

@@ -9,6 +9,7 @@ export { default as Avatar } from './Avatar';
export { default as Tooltip } from './Tooltip';
export { default as Select } from './Select';
export { default as DatePicker } from './DatePicker';
export { Tabs } from './Tabs';
export { ThemeToggle } from './ThemeToggle';
export { ProgressBar } from './ProgressBar';
export { StatusIndicator } from './StatusIndicator';
@@ -29,6 +30,7 @@ export type { AvatarProps } from './Avatar';
export type { TooltipProps } from './Tooltip';
export type { SelectProps, SelectOption } from './Select';
export type { DatePickerProps } from './DatePicker';
export type { TabsProps, TabItem } from './Tabs';
export type { ThemeToggleProps } from './ThemeToggle';
export type { ProgressBarProps } from './ProgressBar';
export type { StatusIndicatorProps } from './StatusIndicator';