Create the frontend receipes page to use real API 2
This commit is contained in:
@@ -57,7 +57,7 @@ export const CreateRecipeModal: React.FC<CreateRecipeModalProps> = ({
|
||||
});
|
||||
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [mode, setMode] = useState<'overview' | 'edit'>('edit');
|
||||
const [mode, setMode] = useState<'view' | 'edit'>('edit');
|
||||
|
||||
// Get tenant and fetch inventory data
|
||||
const currentTenant = useCurrentTenant();
|
||||
@@ -280,7 +280,8 @@ export const CreateRecipeModal: React.FC<CreateRecipeModalProps> = ({
|
||||
}
|
||||
};
|
||||
|
||||
const getModalSections = () => [
|
||||
const getModalSections = () => {
|
||||
const sections = [
|
||||
{
|
||||
title: 'Información Básica',
|
||||
icon: ChefHat,
|
||||
@@ -588,12 +589,21 @@ export const CreateRecipeModal: React.FC<CreateRecipeModalProps> = ({
|
||||
}
|
||||
];
|
||||
|
||||
// Add editable: true to all fields since this is a creation modal
|
||||
return sections.map(section => ({
|
||||
...section,
|
||||
fields: section.fields.map(field => ({
|
||||
...field,
|
||||
editable: field.readonly !== true // Make editable unless explicitly readonly
|
||||
}))
|
||||
}));
|
||||
};
|
||||
|
||||
return (
|
||||
<StatusModal
|
||||
isOpen={isOpen}
|
||||
onClose={onClose}
|
||||
mode={mode}
|
||||
onModeChange={setMode}
|
||||
mode="edit"
|
||||
title="Nueva Receta"
|
||||
subtitle="Crear una nueva receta para la panadería"
|
||||
statusIndicator={{
|
||||
@@ -606,15 +616,9 @@ export const CreateRecipeModal: React.FC<CreateRecipeModalProps> = ({
|
||||
size="xl"
|
||||
sections={getModalSections()}
|
||||
onFieldChange={handleFieldChange}
|
||||
actions={[
|
||||
{
|
||||
label: loading ? 'Creando...' : 'Crear Receta',
|
||||
icon: ChefHat,
|
||||
variant: 'primary',
|
||||
onClick: handleSubmit,
|
||||
disabled: loading || !formData.name.trim() || !formData.finished_product_id.trim()
|
||||
}
|
||||
]}
|
||||
showDefaultActions={true}
|
||||
onSave={handleSubmit}
|
||||
onCancel={onClose}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
122
frontend/src/components/ui/Tabs/Tabs.tsx
Normal file
122
frontend/src/components/ui/Tabs/Tabs.tsx
Normal 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;
|
||||
2
frontend/src/components/ui/Tabs/index.ts
Normal file
2
frontend/src/components/ui/Tabs/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export { default as Tabs } from './Tabs';
|
||||
export type { TabsProps, TabItem } from './Tabs';
|
||||
@@ -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';
|
||||
|
||||
Reference in New Issue
Block a user