Fix frontend 1
This commit is contained in:
@@ -286,7 +286,7 @@ const QuickActions: React.FC<QuickActionsProps> = ({
|
||||
'focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2',
|
||||
sizeClasses[size],
|
||||
{
|
||||
'bg-white hover:bg-[var(--bg-secondary)]': !action.backgroundGradient,
|
||||
'bg-[var(--bg-primary)] hover:bg-[var(--bg-secondary)]': !action.backgroundGradient,
|
||||
'bg-gradient-to-br text-white hover:opacity-90': action.backgroundGradient,
|
||||
'opacity-50 cursor-not-allowed hover:transform-none hover:shadow-none': isDisabled,
|
||||
}
|
||||
|
||||
@@ -499,7 +499,7 @@ export const InventoryForm: React.FC<InventoryFormProps> = ({
|
||||
type="number"
|
||||
step="0.01"
|
||||
min="0"
|
||||
value={formData.low_stock_threshold.toString()}
|
||||
value={formData.low_stock_threshold?.toString() || ''}
|
||||
onChange={(e) => handleInputChange('low_stock_threshold', parseFloat(e.target.value) || 0)}
|
||||
error={errors.low_stock_threshold}
|
||||
placeholder="10"
|
||||
@@ -510,7 +510,7 @@ export const InventoryForm: React.FC<InventoryFormProps> = ({
|
||||
type="number"
|
||||
step="0.01"
|
||||
min="0"
|
||||
value={formData.reorder_point.toString()}
|
||||
value={formData.reorder_point?.toString() || ''}
|
||||
onChange={(e) => handleInputChange('reorder_point', parseFloat(e.target.value) || 0)}
|
||||
error={errors.reorder_point}
|
||||
placeholder="20"
|
||||
@@ -521,7 +521,7 @@ export const InventoryForm: React.FC<InventoryFormProps> = ({
|
||||
type="number"
|
||||
step="0.01"
|
||||
min="0"
|
||||
value={formData.reorder_quantity.toString()}
|
||||
value={formData.reorder_quantity?.toString() || ''}
|
||||
onChange={(e) => handleInputChange('reorder_quantity', parseFloat(e.target.value) || 0)}
|
||||
error={errors.reorder_quantity}
|
||||
placeholder="50"
|
||||
|
||||
@@ -205,6 +205,7 @@ export const AppShell = forwardRef<AppShellRef, AppShellProps>(({
|
||||
isOpen={isSidebarOpen}
|
||||
isCollapsed={isSidebarCollapsed}
|
||||
onClose={() => setIsSidebarOpen(false)}
|
||||
onToggleCollapse={toggleSidebar}
|
||||
className="z-[var(--z-fixed)]"
|
||||
/>
|
||||
|
||||
@@ -223,15 +224,13 @@ export const AppShell = forwardRef<AppShellRef, AppShellProps>(({
|
||||
<main
|
||||
className={clsx(
|
||||
'flex-1 flex flex-col transition-all duration-300 ease-in-out',
|
||||
// Adjust margins based on sidebar state
|
||||
shouldShowSidebar && isAuthenticated && {
|
||||
'lg:ml-[var(--sidebar-width)]': !isSidebarCollapsed,
|
||||
'lg:ml-16': isSidebarCollapsed,
|
||||
},
|
||||
// Add header offset
|
||||
shouldShowHeader && 'pt-[var(--header-height)]',
|
||||
// Adjust margins based on sidebar state
|
||||
shouldShowSidebar && isAuthenticated && !isSidebarCollapsed && 'lg:ml-[var(--sidebar-width)]',
|
||||
shouldShowSidebar && isAuthenticated && isSidebarCollapsed && 'lg:ml-[var(--sidebar-collapsed-width)]',
|
||||
// Add padding to content
|
||||
padded && 'p-4 lg:p-6'
|
||||
padded && 'px-4 lg:px-6 pb-4 lg:pb-6'
|
||||
)}
|
||||
role="main"
|
||||
aria-label="Contenido principal"
|
||||
@@ -247,10 +246,8 @@ export const AppShell = forwardRef<AppShellRef, AppShellProps>(({
|
||||
showPrivacyLinks={true}
|
||||
className={clsx(
|
||||
'transition-all duration-300 ease-in-out',
|
||||
shouldShowSidebar && isAuthenticated && {
|
||||
'lg:ml-[var(--sidebar-width)]': !isSidebarCollapsed,
|
||||
'lg:ml-16': isSidebarCollapsed,
|
||||
}
|
||||
shouldShowSidebar && isAuthenticated && !isSidebarCollapsed && 'lg:ml-[var(--sidebar-width)]',
|
||||
shouldShowSidebar && isAuthenticated && isSidebarCollapsed && 'lg:ml-[var(--sidebar-collapsed-width)]'
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -40,6 +40,10 @@ export interface SidebarProps {
|
||||
* Callback when sidebar is closed (mobile)
|
||||
*/
|
||||
onClose?: () => void;
|
||||
/**
|
||||
* Callback when sidebar collapse state is toggled (desktop)
|
||||
*/
|
||||
onToggleCollapse?: () => void;
|
||||
/**
|
||||
* Custom navigation items
|
||||
*/
|
||||
@@ -110,6 +114,7 @@ export const Sidebar = forwardRef<SidebarRef, SidebarProps>(({
|
||||
isOpen = false,
|
||||
isCollapsed = false,
|
||||
onClose,
|
||||
onToggleCollapse,
|
||||
customItems,
|
||||
showCollapseButton = true,
|
||||
showFooter = true,
|
||||
@@ -340,12 +345,12 @@ export const Sidebar = forwardRef<SidebarRef, SidebarProps>(({
|
||||
disabled={item.disabled}
|
||||
data-path={item.path}
|
||||
className={clsx(
|
||||
'w-full p-3 rounded-lg transition-all duration-200',
|
||||
'w-full rounded-lg transition-all duration-200',
|
||||
'focus:outline-none focus:ring-2 focus:ring-[var(--color-primary)]/20',
|
||||
isActive && 'bg-[var(--color-primary)]/10 border-l-2 border-[var(--color-primary)]',
|
||||
!isActive && 'hover:bg-[var(--bg-secondary)]',
|
||||
item.disabled && 'opacity-50 cursor-not-allowed',
|
||||
isCollapsed && !hasChildren && 'flex justify-center p-3'
|
||||
isCollapsed && !hasChildren ? 'flex justify-center items-center p-2 mx-1' : 'p-3'
|
||||
)}
|
||||
aria-expanded={hasChildren ? isExpanded : undefined}
|
||||
aria-current={isActive ? 'page' : undefined}
|
||||
@@ -388,29 +393,29 @@ export const Sidebar = forwardRef<SidebarRef, SidebarProps>(({
|
||||
'bg-[var(--bg-primary)] border-r border-[var(--border-primary)]',
|
||||
'transition-all duration-300 ease-in-out z-[var(--z-fixed)]',
|
||||
'hidden lg:flex lg:flex-col',
|
||||
isCollapsed ? 'w-16' : 'w-[var(--sidebar-width)]',
|
||||
isCollapsed ? 'w-[var(--sidebar-collapsed-width)]' : 'w-[var(--sidebar-width)]',
|
||||
className
|
||||
)}
|
||||
aria-label="Navegación principal"
|
||||
>
|
||||
{/* Navigation */}
|
||||
<nav className="flex-1 p-4 overflow-y-auto">
|
||||
<ul className="space-y-2">
|
||||
<nav className={clsx('flex-1 overflow-y-auto', isCollapsed ? 'px-1 py-4' : 'p-4')}>
|
||||
<ul className={clsx(isCollapsed ? 'space-y-1' : 'space-y-2')}>
|
||||
{visibleItems.map(item => renderItem(item))}
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
{/* Collapse button */}
|
||||
{showCollapseButton && (
|
||||
<div className="p-4 border-t border-[var(--border-primary)]">
|
||||
<div className={clsx('border-t border-[var(--border-primary)]', isCollapsed ? 'p-2' : 'p-4')}>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => {
|
||||
// This should be handled by parent component
|
||||
console.log('Toggle collapse');
|
||||
}}
|
||||
className="w-full flex items-center justify-center"
|
||||
onClick={onToggleCollapse}
|
||||
className={clsx(
|
||||
'w-full flex items-center justify-center',
|
||||
isCollapsed ? 'p-2' : 'px-4 py-2'
|
||||
)}
|
||||
aria-label={isCollapsed ? 'Expandir sidebar' : 'Contraer sidebar'}
|
||||
>
|
||||
{isCollapsed ? (
|
||||
|
||||
@@ -229,14 +229,14 @@ const Table = forwardRef<HTMLTableElement, TableProps>(({
|
||||
};
|
||||
|
||||
const variantClasses = {
|
||||
default: 'border-collapse border border-table-border',
|
||||
default: 'border-collapse',
|
||||
striped: 'border-collapse',
|
||||
bordered: 'border-collapse border border-table-border',
|
||||
bordered: 'border-collapse border border-[var(--border-primary)]',
|
||||
borderless: 'border-collapse',
|
||||
};
|
||||
|
||||
const tableClasses = clsx(
|
||||
'w-full bg-table-bg',
|
||||
'w-full bg-[var(--bg-primary)]',
|
||||
sizeClasses[size],
|
||||
variantClasses[variant],
|
||||
{
|
||||
@@ -285,10 +285,10 @@ const Table = forwardRef<HTMLTableElement, TableProps>(({
|
||||
const hasExpansion = expandable;
|
||||
|
||||
return (
|
||||
<thead className={clsx('bg-table-header-bg', { 'sticky top-0 z-10': sticky })}>
|
||||
<thead className={clsx('bg-[var(--bg-secondary)]', { 'sticky top-0 z-10': sticky })}>
|
||||
<tr>
|
||||
{hasSelection && (
|
||||
<th className="px-4 py-3 text-left font-medium text-text-primary border-b border-table-border w-12">
|
||||
<th className="px-4 py-3 text-left font-medium text-[var(--text-primary)] border-b border-[var(--border-primary)] w-12">
|
||||
{rowSelection.type !== 'radio' && (
|
||||
<input
|
||||
type="checkbox"
|
||||
@@ -302,7 +302,7 @@ const Table = forwardRef<HTMLTableElement, TableProps>(({
|
||||
</th>
|
||||
)}
|
||||
{hasExpansion && (
|
||||
<th className="px-4 py-3 text-left font-medium text-text-primary border-b border-table-border w-12"></th>
|
||||
<th className="px-4 py-3 text-left font-medium text-[var(--text-primary)] border-b border-[var(--border-primary)] w-12"></th>
|
||||
)}
|
||||
{columns.map((column) => {
|
||||
const isSorted = sortState.field === (column.sortKey || column.key);
|
||||
@@ -311,12 +311,12 @@ const Table = forwardRef<HTMLTableElement, TableProps>(({
|
||||
<th
|
||||
key={column.key}
|
||||
className={clsx(
|
||||
'px-4 py-3 font-medium text-text-primary border-b border-table-border',
|
||||
'px-4 py-3 font-medium text-[var(--text-primary)] border-b border-[var(--border-primary)]',
|
||||
{
|
||||
'text-left': column.align === 'left' || !column.align,
|
||||
'text-center': column.align === 'center',
|
||||
'text-right': column.align === 'right',
|
||||
'cursor-pointer hover:bg-table-row-hover': column.sortable,
|
||||
'cursor-pointer hover:bg-[var(--bg-secondary)] transition-colors duration-150': column.sortable,
|
||||
},
|
||||
column.headerClassName
|
||||
)}
|
||||
@@ -372,12 +372,13 @@ const Table = forwardRef<HTMLTableElement, TableProps>(({
|
||||
<tr
|
||||
{...rowProps}
|
||||
className={clsx(
|
||||
'transition-colors duration-150',
|
||||
'group transition-colors duration-200 ease-in-out',
|
||||
{
|
||||
'bg-table-row-hover': hover && !isSelected,
|
||||
'bg-table-row-selected': isSelected,
|
||||
'odd:bg-bg-secondary': variant === 'striped' && !isSelected,
|
||||
'border-b border-table-border': variant !== 'borderless',
|
||||
'hover:bg-[var(--bg-secondary)] hover:shadow-sm': hover && !isSelected,
|
||||
'bg-[var(--color-primary)]/10': isSelected,
|
||||
'odd:bg-[var(--bg-tertiary)]/30': variant === 'striped' && !isSelected && !hover,
|
||||
'odd:hover:bg-[var(--bg-secondary)]': variant === 'striped' && hover && !isSelected,
|
||||
'border-b border-[var(--border-primary)]': variant !== 'borderless',
|
||||
'cursor-pointer': expandable?.expandRowByClick,
|
||||
},
|
||||
rowProps.className
|
||||
@@ -385,7 +386,7 @@ const Table = forwardRef<HTMLTableElement, TableProps>(({
|
||||
onClick={expandable?.expandRowByClick ? () => handleExpand(record, !isExpanded) : rowProps.onClick}
|
||||
>
|
||||
{rowSelection && (
|
||||
<td className="px-4 py-3 border-b border-table-border">
|
||||
<td className="px-4 py-3 border-b border-[var(--border-primary)]">
|
||||
<input
|
||||
type={rowSelection.type || 'checkbox'}
|
||||
className="rounded border-input-border focus:ring-color-primary"
|
||||
@@ -398,7 +399,7 @@ const Table = forwardRef<HTMLTableElement, TableProps>(({
|
||||
</td>
|
||||
)}
|
||||
{expandable && (
|
||||
<td className="px-4 py-3 border-b border-table-border">
|
||||
<td className="px-4 py-3 border-b border-[var(--border-primary)]">
|
||||
{canExpand && (
|
||||
<button
|
||||
type="button"
|
||||
@@ -431,11 +432,12 @@ const Table = forwardRef<HTMLTableElement, TableProps>(({
|
||||
<td
|
||||
key={column.key}
|
||||
className={clsx(
|
||||
'px-4 py-3 border-b border-table-border',
|
||||
'px-4 py-3 border-b border-[var(--border-primary)] transition-colors duration-200 ease-in-out',
|
||||
{
|
||||
'text-left': column.align === 'left' || !column.align,
|
||||
'text-center': column.align === 'center',
|
||||
'text-right': column.align === 'right',
|
||||
'group-hover:text-[var(--text-primary)]': true,
|
||||
},
|
||||
column.className
|
||||
)}
|
||||
@@ -450,7 +452,7 @@ const Table = forwardRef<HTMLTableElement, TableProps>(({
|
||||
<tr>
|
||||
<td
|
||||
colSpan={columns.length + (rowSelection ? 1 : 0) + (expandable ? 1 : 0)}
|
||||
className="px-4 py-0 border-b border-table-border bg-bg-secondary"
|
||||
className="px-4 py-0 border-b border-[var(--border-primary)] bg-[var(--bg-secondary)]"
|
||||
>
|
||||
<div className="py-4" style={{ paddingLeft: expandable.indentSize || 24 }}>
|
||||
{expandable.expandedRowRender(record, index)}
|
||||
@@ -462,7 +464,7 @@ const Table = forwardRef<HTMLTableElement, TableProps>(({
|
||||
);
|
||||
})}
|
||||
{summary && (
|
||||
<tr className="bg-table-header-bg border-t-2 border-table-border font-medium">
|
||||
<tr className="bg-[var(--bg-secondary)] border-t-2 border-[var(--border-primary)] font-medium">
|
||||
<td colSpan={columns.length + (rowSelection ? 1 : 0) + (expandable ? 1 : 0)}>
|
||||
{summary(data)}
|
||||
</td>
|
||||
@@ -472,8 +474,8 @@ const Table = forwardRef<HTMLTableElement, TableProps>(({
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<div className={containerClasses}>
|
||||
<div className="space-y-4 bg-[var(--bg-primary)]">
|
||||
<div className={clsx(containerClasses, 'bg-[var(--bg-primary)]')}>
|
||||
<table
|
||||
ref={ref}
|
||||
className={tableClasses}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React, { useState } from 'react';
|
||||
import { Calendar, TrendingUp, AlertTriangle, BarChart3, Download, Settings } from 'lucide-react';
|
||||
import { Button, Card, Badge, Select } from '../../../../components/ui';
|
||||
import { Button, Card, Badge, Select, Table } from '../../../../components/ui';
|
||||
import type { TableColumn } from '../../../../components/ui';
|
||||
import { PageHeader } from '../../../../components/layout';
|
||||
import { DemandChart, ForecastTable, SeasonalityIndicator, AlertsPanel } from '../../../../components/domain/forecasting';
|
||||
|
||||
@@ -125,6 +126,57 @@ const ForecastingPage: React.FC = () => {
|
||||
return <Badge variant={config?.color as any}>{config?.text}</Badge>;
|
||||
};
|
||||
|
||||
const forecastColumns: TableColumn[] = [
|
||||
{
|
||||
key: 'product',
|
||||
title: 'Producto',
|
||||
dataIndex: 'product',
|
||||
},
|
||||
{
|
||||
key: 'currentStock',
|
||||
title: 'Stock Actual',
|
||||
dataIndex: 'currentStock',
|
||||
},
|
||||
{
|
||||
key: 'forecastDemand',
|
||||
title: 'Demanda Prevista',
|
||||
dataIndex: 'forecastDemand',
|
||||
render: (value) => (
|
||||
<span className="font-medium text-[var(--color-info)]">{value}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'recommendedProduction',
|
||||
title: 'Producción Recomendada',
|
||||
dataIndex: 'recommendedProduction',
|
||||
render: (value) => (
|
||||
<span className="font-medium text-[var(--color-success)]">{value}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'confidence',
|
||||
title: 'Confianza',
|
||||
dataIndex: 'confidence',
|
||||
render: (value) => `${value}%`,
|
||||
},
|
||||
{
|
||||
key: 'trend',
|
||||
title: 'Tendencia',
|
||||
dataIndex: 'trend',
|
||||
render: (value) => (
|
||||
<div className="flex items-center">
|
||||
{getTrendIcon(value)}
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'stockoutRisk',
|
||||
title: 'Riesgo Agotamiento',
|
||||
dataIndex: 'stockoutRisk',
|
||||
render: (value) => getRiskBadge(value),
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="p-6 space-y-6">
|
||||
<PageHeader
|
||||
@@ -315,68 +367,16 @@ const ForecastingPage: React.FC = () => {
|
||||
</div>
|
||||
|
||||
{/* Detailed Forecasts Table */}
|
||||
<Card>
|
||||
<div className="p-6">
|
||||
<h3 className="text-lg font-semibold text-[var(--text-primary)] mb-4">Predicciones Detalladas</h3>
|
||||
<div className="overflow-x-auto">
|
||||
<table className="min-w-full divide-y divide-gray-200">
|
||||
<thead className="bg-[var(--bg-secondary)]">
|
||||
<tr>
|
||||
<th className="px-6 py-3 text-left text-xs font-medium text-[var(--text-tertiary)] uppercase tracking-wider">
|
||||
Producto
|
||||
</th>
|
||||
<th className="px-6 py-3 text-left text-xs font-medium text-[var(--text-tertiary)] uppercase tracking-wider">
|
||||
Stock Actual
|
||||
</th>
|
||||
<th className="px-6 py-3 text-left text-xs font-medium text-[var(--text-tertiary)] uppercase tracking-wider">
|
||||
Demanda Prevista
|
||||
</th>
|
||||
<th className="px-6 py-3 text-left text-xs font-medium text-[var(--text-tertiary)] uppercase tracking-wider">
|
||||
Producción Recomendada
|
||||
</th>
|
||||
<th className="px-6 py-3 text-left text-xs font-medium text-[var(--text-tertiary)] uppercase tracking-wider">
|
||||
Confianza
|
||||
</th>
|
||||
<th className="px-6 py-3 text-left text-xs font-medium text-[var(--text-tertiary)] uppercase tracking-wider">
|
||||
Tendencia
|
||||
</th>
|
||||
<th className="px-6 py-3 text-left text-xs font-medium text-[var(--text-tertiary)] uppercase tracking-wider">
|
||||
Riesgo Agotamiento
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="bg-white divide-y divide-gray-200">
|
||||
{mockForecasts.map((forecast) => (
|
||||
<tr key={forecast.id} className="hover:bg-[var(--bg-secondary)]">
|
||||
<td className="px-6 py-4 whitespace-nowrap">
|
||||
<div className="text-sm font-medium text-[var(--text-primary)]">{forecast.product}</div>
|
||||
</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-[var(--text-primary)]">
|
||||
{forecast.currentStock}
|
||||
</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-[var(--color-info)]">
|
||||
{forecast.forecastDemand}
|
||||
</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-[var(--color-success)]">
|
||||
{forecast.recommendedProduction}
|
||||
</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-[var(--text-primary)]">
|
||||
{forecast.confidence}%
|
||||
</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap">
|
||||
<div className="flex items-center">
|
||||
{getTrendIcon(forecast.trend)}
|
||||
</div>
|
||||
</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap">
|
||||
{getRiskBadge(forecast.stockoutRisk)}
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<Card className="p-6">
|
||||
<h3 className="text-lg font-semibold text-[var(--text-primary)] mb-4">Predicciones Detalladas</h3>
|
||||
<Table
|
||||
columns={forecastColumns}
|
||||
data={mockForecasts}
|
||||
rowKey="id"
|
||||
hover={true}
|
||||
variant="default"
|
||||
size="md"
|
||||
/>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React, { useState } from 'react';
|
||||
import { Plus, Search, Filter, Download, Calendar, Clock, User, Package } from 'lucide-react';
|
||||
import { Button, Input, Card, Badge } from '../../../../components/ui';
|
||||
import { Button, Input, Card, Badge, Table } from '../../../../components/ui';
|
||||
import type { TableColumn } from '../../../../components/ui';
|
||||
import { PageHeader } from '../../../../components/layout';
|
||||
import { OrdersTable, OrderForm } from '../../../../components/domain/sales';
|
||||
|
||||
@@ -115,6 +116,114 @@ const OrdersPage: React.FC = () => {
|
||||
return <Badge variant={config?.color as any}>{config?.text || status}</Badge>;
|
||||
};
|
||||
|
||||
const columns: TableColumn[] = [
|
||||
{
|
||||
key: 'id',
|
||||
title: 'Pedido',
|
||||
dataIndex: 'id',
|
||||
render: (value, record: any) => (
|
||||
<div>
|
||||
<div className="text-sm font-medium text-[var(--text-primary)]">{value}</div>
|
||||
<div className="text-xs text-[var(--text-tertiary)]">{record.deliveryMethod === 'delivery' ? 'Entrega' : 'Recogida'}</div>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'customer',
|
||||
title: 'Cliente',
|
||||
render: (_, record: any) => (
|
||||
<div className="flex items-center">
|
||||
<User className="h-4 w-4 text-[var(--text-tertiary)] mr-2" />
|
||||
<div>
|
||||
<div className="text-sm font-medium text-[var(--text-primary)]">{record.customerName}</div>
|
||||
<div className="text-xs text-[var(--text-tertiary)]">{record.customerEmail}</div>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'status',
|
||||
title: 'Estado',
|
||||
dataIndex: 'status',
|
||||
render: (value) => getStatusBadge(value),
|
||||
},
|
||||
{
|
||||
key: 'priority',
|
||||
title: 'Prioridad',
|
||||
dataIndex: 'priority',
|
||||
render: (value) => getPriorityBadge(value),
|
||||
},
|
||||
{
|
||||
key: 'orderDate',
|
||||
title: 'Fecha Pedido',
|
||||
dataIndex: 'orderDate',
|
||||
render: (value) => (
|
||||
<div>
|
||||
<div className="text-sm text-[var(--text-primary)]">{new Date(value).toLocaleDateString('es-ES')}</div>
|
||||
<div className="text-xs text-[var(--text-tertiary)]">
|
||||
{new Date(value).toLocaleTimeString('es-ES', { hour: '2-digit', minute: '2-digit' })}
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'deliveryDate',
|
||||
title: 'Entrega',
|
||||
dataIndex: 'deliveryDate',
|
||||
render: (value) => (
|
||||
<div>
|
||||
<div className="text-sm text-[var(--text-primary)]">{new Date(value).toLocaleDateString('es-ES')}</div>
|
||||
<div className="text-xs text-[var(--text-tertiary)]">
|
||||
{new Date(value).toLocaleTimeString('es-ES', { hour: '2-digit', minute: '2-digit' })}
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'total',
|
||||
title: 'Total',
|
||||
dataIndex: 'total',
|
||||
render: (value, record: any) => (
|
||||
<div>
|
||||
<div className="text-sm font-medium text-[var(--text-primary)]">€{value.toFixed(2)}</div>
|
||||
<div className="text-xs text-[var(--text-tertiary)]">{record.items.length} artículos</div>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'payment',
|
||||
title: 'Pago',
|
||||
render: (_, record: any) => (
|
||||
<div>
|
||||
{getPaymentStatusBadge(record.paymentStatus)}
|
||||
<div className="text-xs text-[var(--text-tertiary)] capitalize">{record.paymentMethod}</div>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'actions',
|
||||
title: 'Acciones',
|
||||
align: 'right' as const,
|
||||
render: (_, record: any) => (
|
||||
<div className="flex space-x-2">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => {
|
||||
setSelectedOrder(record);
|
||||
setShowForm(true);
|
||||
}}
|
||||
>
|
||||
Ver
|
||||
</Button>
|
||||
<Button variant="outline" size="sm">
|
||||
Editar
|
||||
</Button>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
const filteredOrders = mockOrders.filter(order => {
|
||||
const matchesSearch = order.customerName.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||
order.id.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||
@@ -276,110 +385,15 @@ const OrdersPage: React.FC = () => {
|
||||
</Card>
|
||||
|
||||
{/* Orders Table */}
|
||||
<Card>
|
||||
<div className="overflow-x-auto">
|
||||
<table className="min-w-full divide-y divide-gray-200">
|
||||
<thead className="bg-[var(--bg-secondary)]">
|
||||
<tr>
|
||||
<th className="px-6 py-3 text-left text-xs font-medium text-[var(--text-tertiary)] uppercase tracking-wider">
|
||||
Pedido
|
||||
</th>
|
||||
<th className="px-6 py-3 text-left text-xs font-medium text-[var(--text-tertiary)] uppercase tracking-wider">
|
||||
Cliente
|
||||
</th>
|
||||
<th className="px-6 py-3 text-left text-xs font-medium text-[var(--text-tertiary)] uppercase tracking-wider">
|
||||
Estado
|
||||
</th>
|
||||
<th className="px-6 py-3 text-left text-xs font-medium text-[var(--text-tertiary)] uppercase tracking-wider">
|
||||
Prioridad
|
||||
</th>
|
||||
<th className="px-6 py-3 text-left text-xs font-medium text-[var(--text-tertiary)] uppercase tracking-wider">
|
||||
Fecha Pedido
|
||||
</th>
|
||||
<th className="px-6 py-3 text-left text-xs font-medium text-[var(--text-tertiary)] uppercase tracking-wider">
|
||||
Entrega
|
||||
</th>
|
||||
<th className="px-6 py-3 text-left text-xs font-medium text-[var(--text-tertiary)] uppercase tracking-wider">
|
||||
Total
|
||||
</th>
|
||||
<th className="px-6 py-3 text-left text-xs font-medium text-[var(--text-tertiary)] uppercase tracking-wider">
|
||||
Pago
|
||||
</th>
|
||||
<th className="px-6 py-3 text-left text-xs font-medium text-[var(--text-tertiary)] uppercase tracking-wider">
|
||||
Acciones
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="bg-white divide-y divide-gray-200">
|
||||
{filteredOrders.map((order) => (
|
||||
<tr key={order.id} className="hover:bg-[var(--bg-secondary)]">
|
||||
<td className="px-6 py-4 whitespace-nowrap">
|
||||
<div className="text-sm font-medium text-[var(--text-primary)]">{order.id}</div>
|
||||
<div className="text-xs text-[var(--text-tertiary)]">{order.deliveryMethod === 'delivery' ? 'Entrega' : 'Recogida'}</div>
|
||||
</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap">
|
||||
<div className="flex items-center">
|
||||
<User className="h-4 w-4 text-[var(--text-tertiary)] mr-2" />
|
||||
<div>
|
||||
<div className="text-sm font-medium text-[var(--text-primary)]">{order.customerName}</div>
|
||||
<div className="text-xs text-[var(--text-tertiary)]">{order.customerEmail}</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap">
|
||||
{getStatusBadge(order.status)}
|
||||
</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap">
|
||||
{getPriorityBadge(order.priority)}
|
||||
</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-[var(--text-primary)]">
|
||||
{new Date(order.orderDate).toLocaleDateString('es-ES')}
|
||||
<div className="text-xs text-[var(--text-tertiary)]">
|
||||
{new Date(order.orderDate).toLocaleTimeString('es-ES', {
|
||||
hour: '2-digit',
|
||||
minute: '2-digit'
|
||||
})}
|
||||
</div>
|
||||
</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-[var(--text-primary)]">
|
||||
{new Date(order.deliveryDate).toLocaleDateString('es-ES')}
|
||||
<div className="text-xs text-[var(--text-tertiary)]">
|
||||
{new Date(order.deliveryDate).toLocaleTimeString('es-ES', {
|
||||
hour: '2-digit',
|
||||
minute: '2-digit'
|
||||
})}
|
||||
</div>
|
||||
</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap">
|
||||
<div className="text-sm font-medium text-[var(--text-primary)]">€{order.total.toFixed(2)}</div>
|
||||
<div className="text-xs text-[var(--text-tertiary)]">{order.items.length} artículos</div>
|
||||
</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap">
|
||||
{getPaymentStatusBadge(order.paymentStatus)}
|
||||
<div className="text-xs text-[var(--text-tertiary)] capitalize">{order.paymentMethod}</div>
|
||||
</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
||||
<div className="flex space-x-2">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => {
|
||||
setSelectedOrder(order);
|
||||
setShowForm(true);
|
||||
}}
|
||||
>
|
||||
Ver
|
||||
</Button>
|
||||
<Button variant="outline" size="sm">
|
||||
Editar
|
||||
</Button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<Card className="p-6">
|
||||
<Table
|
||||
columns={columns}
|
||||
data={filteredOrders}
|
||||
rowKey="id"
|
||||
hover={true}
|
||||
variant="default"
|
||||
size="md"
|
||||
/>
|
||||
</Card>
|
||||
|
||||
{/* Order Form Modal */}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React, { useState } from 'react';
|
||||
import { Plus, Search, Filter, Download, ShoppingCart, Truck, DollarSign, Calendar } from 'lucide-react';
|
||||
import { Button, Input, Card, Badge } from '../../../../components/ui';
|
||||
import { Button, Input, Card, Badge, Table } from '../../../../components/ui';
|
||||
import type { TableColumn } from '../../../../components/ui';
|
||||
import { PageHeader } from '../../../../components/layout';
|
||||
|
||||
const ProcurementPage: React.FC = () => {
|
||||
@@ -124,6 +125,68 @@ const ProcurementPage: React.FC = () => {
|
||||
return <Badge variant={config?.color as any}>{config?.text || status}</Badge>;
|
||||
};
|
||||
|
||||
const columns: TableColumn[] = [
|
||||
{
|
||||
key: 'id',
|
||||
title: 'Orden',
|
||||
dataIndex: 'id',
|
||||
render: (value, record: any) => (
|
||||
<div>
|
||||
<div className="text-sm font-medium text-[var(--text-primary)]">{value}</div>
|
||||
{record.notes && (
|
||||
<div className="text-xs text-[var(--text-tertiary)]">{record.notes}</div>
|
||||
)}
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'supplier',
|
||||
title: 'Proveedor',
|
||||
dataIndex: 'supplier',
|
||||
},
|
||||
{
|
||||
key: 'status',
|
||||
title: 'Estado',
|
||||
dataIndex: 'status',
|
||||
render: (value) => getStatusBadge(value),
|
||||
},
|
||||
{
|
||||
key: 'orderDate',
|
||||
title: 'Fecha Pedido',
|
||||
dataIndex: 'orderDate',
|
||||
render: (value) => new Date(value).toLocaleDateString('es-ES'),
|
||||
},
|
||||
{
|
||||
key: 'deliveryDate',
|
||||
title: 'Fecha Entrega',
|
||||
dataIndex: 'deliveryDate',
|
||||
render: (value) => new Date(value).toLocaleDateString('es-ES'),
|
||||
},
|
||||
{
|
||||
key: 'totalAmount',
|
||||
title: 'Monto Total',
|
||||
dataIndex: 'totalAmount',
|
||||
render: (value) => `€${value.toLocaleString()}`,
|
||||
},
|
||||
{
|
||||
key: 'paymentStatus',
|
||||
title: 'Pago',
|
||||
dataIndex: 'paymentStatus',
|
||||
render: (value) => getPaymentStatusBadge(value),
|
||||
},
|
||||
{
|
||||
key: 'actions',
|
||||
title: 'Acciones',
|
||||
align: 'right' as const,
|
||||
render: () => (
|
||||
<div className="flex space-x-2">
|
||||
<Button variant="outline" size="sm">Ver</Button>
|
||||
<Button variant="outline" size="sm">Editar</Button>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
const stats = {
|
||||
totalOrders: mockPurchaseOrders.length,
|
||||
pendingOrders: mockPurchaseOrders.filter(o => o.status === 'pending').length,
|
||||
@@ -253,75 +316,15 @@ const ProcurementPage: React.FC = () => {
|
||||
|
||||
{/* Tab Content */}
|
||||
{activeTab === 'orders' && (
|
||||
<Card>
|
||||
<div className="overflow-x-auto">
|
||||
<table className="min-w-full divide-y divide-gray-200">
|
||||
<thead className="bg-[var(--bg-secondary)]">
|
||||
<tr>
|
||||
<th className="px-6 py-3 text-left text-xs font-medium text-[var(--text-tertiary)] uppercase tracking-wider">
|
||||
Orden
|
||||
</th>
|
||||
<th className="px-6 py-3 text-left text-xs font-medium text-[var(--text-tertiary)] uppercase tracking-wider">
|
||||
Proveedor
|
||||
</th>
|
||||
<th className="px-6 py-3 text-left text-xs font-medium text-[var(--text-tertiary)] uppercase tracking-wider">
|
||||
Estado
|
||||
</th>
|
||||
<th className="px-6 py-3 text-left text-xs font-medium text-[var(--text-tertiary)] uppercase tracking-wider">
|
||||
Fecha Pedido
|
||||
</th>
|
||||
<th className="px-6 py-3 text-left text-xs font-medium text-[var(--text-tertiary)] uppercase tracking-wider">
|
||||
Fecha Entrega
|
||||
</th>
|
||||
<th className="px-6 py-3 text-left text-xs font-medium text-[var(--text-tertiary)] uppercase tracking-wider">
|
||||
Monto Total
|
||||
</th>
|
||||
<th className="px-6 py-3 text-left text-xs font-medium text-[var(--text-tertiary)] uppercase tracking-wider">
|
||||
Pago
|
||||
</th>
|
||||
<th className="px-6 py-3 text-left text-xs font-medium text-[var(--text-tertiary)] uppercase tracking-wider">
|
||||
Acciones
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="bg-white divide-y divide-gray-200">
|
||||
{mockPurchaseOrders.map((order) => (
|
||||
<tr key={order.id} className="hover:bg-[var(--bg-secondary)]">
|
||||
<td className="px-6 py-4 whitespace-nowrap">
|
||||
<div className="text-sm font-medium text-[var(--text-primary)]">{order.id}</div>
|
||||
{order.notes && (
|
||||
<div className="text-xs text-[var(--text-tertiary)]">{order.notes}</div>
|
||||
)}
|
||||
</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-[var(--text-primary)]">
|
||||
{order.supplier}
|
||||
</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap">
|
||||
{getStatusBadge(order.status)}
|
||||
</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-[var(--text-primary)]">
|
||||
{new Date(order.orderDate).toLocaleDateString('es-ES')}
|
||||
</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-[var(--text-primary)]">
|
||||
{new Date(order.deliveryDate).toLocaleDateString('es-ES')}
|
||||
</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-[var(--text-primary)]">
|
||||
€{order.totalAmount.toLocaleString()}
|
||||
</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap">
|
||||
{getPaymentStatusBadge(order.paymentStatus)}
|
||||
</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
||||
<div className="flex space-x-2">
|
||||
<Button variant="outline" size="sm">Ver</Button>
|
||||
<Button variant="outline" size="sm">Editar</Button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<Card className="p-6">
|
||||
<Table
|
||||
columns={columns}
|
||||
data={mockPurchaseOrders}
|
||||
rowKey="id"
|
||||
hover={true}
|
||||
variant="default"
|
||||
size="md"
|
||||
/>
|
||||
</Card>
|
||||
)}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React, { useState } from 'react';
|
||||
import { Plus, Calendar, Clock, Users, AlertCircle } from 'lucide-react';
|
||||
import { Button, Card, Badge } from '../../../../components/ui';
|
||||
import { Button, Card, Badge, Table } from '../../../../components/ui';
|
||||
import type { TableColumn } from '../../../../components/ui';
|
||||
import { PageHeader } from '../../../../components/layout';
|
||||
import { ProductionSchedule, BatchTracker, QualityControl } from '../../../../components/domain/production';
|
||||
|
||||
@@ -76,6 +77,86 @@ const ProductionPage: React.FC = () => {
|
||||
return <Badge variant={config.color as any}>{config.text}</Badge>;
|
||||
};
|
||||
|
||||
const columns: TableColumn[] = [
|
||||
{
|
||||
key: 'recipeName',
|
||||
title: 'Receta',
|
||||
dataIndex: 'recipeName',
|
||||
render: (value) => (
|
||||
<div className="text-sm font-medium text-[var(--text-primary)]">{value}</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'quantity',
|
||||
title: 'Cantidad',
|
||||
dataIndex: 'quantity',
|
||||
render: (value) => `${value} unidades`,
|
||||
},
|
||||
{
|
||||
key: 'status',
|
||||
title: 'Estado',
|
||||
dataIndex: 'status',
|
||||
render: (value) => getStatusBadge(value),
|
||||
},
|
||||
{
|
||||
key: 'priority',
|
||||
title: 'Prioridad',
|
||||
dataIndex: 'priority',
|
||||
render: (value) => getPriorityBadge(value),
|
||||
},
|
||||
{
|
||||
key: 'assignedTo',
|
||||
title: 'Asignado a',
|
||||
dataIndex: 'assignedTo',
|
||||
render: (value) => (
|
||||
<div className="flex items-center">
|
||||
<Users className="h-4 w-4 text-[var(--text-tertiary)] mr-2" />
|
||||
<span className="text-sm text-[var(--text-primary)]">{value}</span>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'progress',
|
||||
title: 'Progreso',
|
||||
dataIndex: 'progress',
|
||||
render: (value) => (
|
||||
<div className="flex items-center">
|
||||
<div className="w-full bg-[var(--bg-quaternary)] rounded-full h-2 mr-2">
|
||||
<div
|
||||
className="bg-blue-600 h-2 rounded-full"
|
||||
style={{ width: `${value}%` }}
|
||||
></div>
|
||||
</div>
|
||||
<span className="text-sm text-[var(--text-primary)]">{value}%</span>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'estimatedCompletion',
|
||||
title: 'Tiempo Estimado',
|
||||
dataIndex: 'estimatedCompletion',
|
||||
render: (value) => new Date(value).toLocaleTimeString('es-ES', {
|
||||
hour: '2-digit',
|
||||
minute: '2-digit'
|
||||
}),
|
||||
},
|
||||
{
|
||||
key: 'actions',
|
||||
title: 'Acciones',
|
||||
align: 'right' as const,
|
||||
render: () => (
|
||||
<div className="flex space-x-2">
|
||||
<Button variant="outline" size="sm">
|
||||
Ver
|
||||
</Button>
|
||||
<Button variant="outline" size="sm">
|
||||
Editar
|
||||
</Button>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="p-6 space-y-6">
|
||||
<PageHeader
|
||||
@@ -216,87 +297,14 @@ const ProductionPage: React.FC = () => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="overflow-x-auto">
|
||||
<table className="min-w-full divide-y divide-gray-200">
|
||||
<thead className="bg-[var(--bg-secondary)]">
|
||||
<tr>
|
||||
<th className="px-6 py-3 text-left text-xs font-medium text-[var(--text-tertiary)] uppercase tracking-wider">
|
||||
Receta
|
||||
</th>
|
||||
<th className="px-6 py-3 text-left text-xs font-medium text-[var(--text-tertiary)] uppercase tracking-wider">
|
||||
Cantidad
|
||||
</th>
|
||||
<th className="px-6 py-3 text-left text-xs font-medium text-[var(--text-tertiary)] uppercase tracking-wider">
|
||||
Estado
|
||||
</th>
|
||||
<th className="px-6 py-3 text-left text-xs font-medium text-[var(--text-tertiary)] uppercase tracking-wider">
|
||||
Prioridad
|
||||
</th>
|
||||
<th className="px-6 py-3 text-left text-xs font-medium text-[var(--text-tertiary)] uppercase tracking-wider">
|
||||
Asignado a
|
||||
</th>
|
||||
<th className="px-6 py-3 text-left text-xs font-medium text-[var(--text-tertiary)] uppercase tracking-wider">
|
||||
Progreso
|
||||
</th>
|
||||
<th className="px-6 py-3 text-left text-xs font-medium text-[var(--text-tertiary)] uppercase tracking-wider">
|
||||
Tiempo Estimado
|
||||
</th>
|
||||
<th className="px-6 py-3 text-left text-xs font-medium text-[var(--text-tertiary)] uppercase tracking-wider">
|
||||
Acciones
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="bg-white divide-y divide-gray-200">
|
||||
{mockProductionOrders.map((order) => (
|
||||
<tr key={order.id} className="hover:bg-[var(--bg-secondary)]">
|
||||
<td className="px-6 py-4 whitespace-nowrap">
|
||||
<div className="text-sm font-medium text-[var(--text-primary)]">{order.recipeName}</div>
|
||||
</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-[var(--text-primary)]">
|
||||
{order.quantity} unidades
|
||||
</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap">
|
||||
{getStatusBadge(order.status)}
|
||||
</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap">
|
||||
{getPriorityBadge(order.priority)}
|
||||
</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap">
|
||||
<div className="flex items-center">
|
||||
<Users className="h-4 w-4 text-[var(--text-tertiary)] mr-2" />
|
||||
<span className="text-sm text-[var(--text-primary)]">{order.assignedTo}</span>
|
||||
</div>
|
||||
</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap">
|
||||
<div className="flex items-center">
|
||||
<div className="w-full bg-[var(--bg-quaternary)] rounded-full h-2 mr-2">
|
||||
<div
|
||||
className="bg-blue-600 h-2 rounded-full"
|
||||
style={{ width: `${order.progress}%` }}
|
||||
></div>
|
||||
</div>
|
||||
<span className="text-sm text-[var(--text-primary)]">{order.progress}%</span>
|
||||
</div>
|
||||
</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-[var(--text-primary)]">
|
||||
{new Date(order.estimatedCompletion).toLocaleTimeString('es-ES', {
|
||||
hour: '2-digit',
|
||||
minute: '2-digit'
|
||||
})}
|
||||
</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
||||
<Button variant="outline" size="sm" className="mr-2">
|
||||
Ver
|
||||
</Button>
|
||||
<Button variant="outline" size="sm">
|
||||
Editar
|
||||
</Button>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<Table
|
||||
columns={columns}
|
||||
data={mockProductionOrders}
|
||||
rowKey="id"
|
||||
hover={true}
|
||||
variant="default"
|
||||
size="md"
|
||||
/>
|
||||
</div>
|
||||
</Card>
|
||||
)}
|
||||
|
||||
@@ -95,33 +95,28 @@ const RegisterPage: React.FC = () => {
|
||||
<Card className="p-8">
|
||||
{/* Progress indicator */}
|
||||
<div className="mb-8">
|
||||
<div className="flex items-center">
|
||||
{[1, 2, 3].map((stepNumber) => (
|
||||
<div key={stepNumber} className="flex items-center">
|
||||
<div className="flex items-start justify-between">
|
||||
{[
|
||||
{ step: 1, label: 'Datos personales' },
|
||||
{ step: 2, label: 'Información empresarial' },
|
||||
{ step: 3, label: 'Crear cuenta' }
|
||||
].map((stepInfo) => (
|
||||
<div key={stepInfo.step} className="flex flex-col items-center">
|
||||
<div
|
||||
className={`flex items-center justify-center w-8 h-8 rounded-full ${
|
||||
step >= stepNumber
|
||||
step >= stepInfo.step
|
||||
? 'bg-[var(--color-primary)] text-white'
|
||||
: 'bg-[var(--bg-quaternary)] text-[var(--text-tertiary)]'
|
||||
}`}
|
||||
>
|
||||
{stepNumber}
|
||||
{stepInfo.step}
|
||||
</div>
|
||||
{stepNumber < 3 && (
|
||||
<div
|
||||
className={`flex-1 h-0.5 mx-4 ${
|
||||
step > stepNumber ? 'bg-[var(--color-primary)]' : 'bg-[var(--bg-quaternary)]'
|
||||
}`}
|
||||
/>
|
||||
)}
|
||||
<span className="mt-2 text-xs text-[var(--text-secondary)] text-center max-w-[80px]">
|
||||
{stepInfo.label}
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div className="flex justify-between mt-2 text-xs text-[var(--text-secondary)]">
|
||||
<span>Datos personales</span>
|
||||
<span>Información empresarial</span>
|
||||
<span>Crear cuenta</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form onSubmit={handleSubmit} className="space-y-6">
|
||||
@@ -220,15 +215,16 @@ const RegisterPage: React.FC = () => {
|
||||
</label>
|
||||
<Select
|
||||
value={formData.companyType}
|
||||
onValueChange={(value) => handleInputChange('companyType', value)}
|
||||
>
|
||||
<option value="">Selecciona el tipo</option>
|
||||
<option value="traditional">Panadería tradicional</option>
|
||||
<option value="artisan">Panadería artesanal</option>
|
||||
<option value="industrial">Panadería industrial</option>
|
||||
<option value="bakery-cafe">Panadería-cafetería</option>
|
||||
<option value="specialty">Panadería especializada</option>
|
||||
</Select>
|
||||
onChange={(value) => handleInputChange('companyType', value as string)}
|
||||
placeholder="Selecciona el tipo"
|
||||
options={[
|
||||
{ value: "traditional", label: "Panadería tradicional" },
|
||||
{ value: "artisan", label: "Panadería artesanal" },
|
||||
{ value: "industrial", label: "Panadería industrial" },
|
||||
{ value: "bakery-cafe", label: "Panadería-cafetería" },
|
||||
{ value: "specialty", label: "Panadería especializada" }
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
@@ -237,15 +233,16 @@ const RegisterPage: React.FC = () => {
|
||||
</label>
|
||||
<Select
|
||||
value={formData.employeeCount}
|
||||
onValueChange={(value) => handleInputChange('employeeCount', value)}
|
||||
>
|
||||
<option value="">Selecciona el rango</option>
|
||||
<option value="1">Solo yo</option>
|
||||
<option value="2-5">2-5 empleados</option>
|
||||
<option value="6-15">6-15 empleados</option>
|
||||
<option value="16-50">16-50 empleados</option>
|
||||
<option value="51+">Más de 50 empleados</option>
|
||||
</Select>
|
||||
onChange={(value) => handleInputChange('employeeCount', value as string)}
|
||||
placeholder="Selecciona el rango"
|
||||
options={[
|
||||
{ value: "1", label: "Solo yo" },
|
||||
{ value: "2-5", label: "2-5 empleados" },
|
||||
{ value: "6-15", label: "6-15 empleados" },
|
||||
{ value: "16-50", label: "16-50 empleados" },
|
||||
{ value: "51+", label: "Más de 50 empleados" }
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -126,6 +126,7 @@
|
||||
/* Layout */
|
||||
--container-max-width: 1280px;
|
||||
--sidebar-width: 280px;
|
||||
--sidebar-collapsed-width: 64px;
|
||||
--header-height: 64px;
|
||||
--footer-height: 56px;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user