Imporve the routes and the menu
This commit is contained in:
@@ -76,10 +76,9 @@ export const OrderFormModal: React.FC<OrderFormModalProps> = ({
|
||||
priority_level: PriorityLevel.NORMAL
|
||||
});
|
||||
|
||||
// Product selection
|
||||
const [showProductModal, setShowProductModal] = useState(false);
|
||||
const [productSearch, setProductSearch] = useState('');
|
||||
const [selectedCategory, setSelectedCategory] = useState<string>('');
|
||||
// Simple product selection
|
||||
const [selectedProductId, setSelectedProductId] = useState('');
|
||||
const [selectedQuantity, setSelectedQuantity] = useState(1);
|
||||
|
||||
// API hooks
|
||||
const { data: customers = [] } = useCustomers({
|
||||
@@ -110,8 +109,8 @@ export const OrderFormModal: React.FC<OrderFormModalProps> = ({
|
||||
// Reset form when modal closes
|
||||
setSelectedCustomer(null);
|
||||
setOrderItems([]);
|
||||
setProductSearch('');
|
||||
setSelectedCategory('');
|
||||
setSelectedProductId('');
|
||||
setSelectedQuantity(1);
|
||||
setOrderData({
|
||||
order_type: OrderType.STANDARD,
|
||||
priority: PriorityLevel.NORMAL,
|
||||
@@ -125,13 +124,18 @@ export const OrderFormModal: React.FC<OrderFormModalProps> = ({
|
||||
}
|
||||
}, [isOpen]);
|
||||
|
||||
const handleAddProduct = (product: any) => {
|
||||
const existingItem = orderItems.find(item => item.product_id === product.id);
|
||||
const handleAddSelectedProduct = () => {
|
||||
if (!selectedProductId || selectedQuantity <= 0) return;
|
||||
|
||||
const product = finishedProducts.find(p => p.id === selectedProductId);
|
||||
if (!product) return;
|
||||
|
||||
const existingItem = orderItems.find(item => item.product_id === selectedProductId);
|
||||
|
||||
if (existingItem) {
|
||||
setOrderItems(items => items.map(item =>
|
||||
item.product_id === product.id
|
||||
? { ...item, quantity: item.quantity + 1 }
|
||||
item.product_id === selectedProductId
|
||||
? { ...item, quantity: item.quantity + selectedQuantity }
|
||||
: item
|
||||
));
|
||||
} else {
|
||||
@@ -140,14 +144,17 @@ export const OrderFormModal: React.FC<OrderFormModalProps> = ({
|
||||
product_name: product.name,
|
||||
product_sku: product.sku || undefined,
|
||||
product_category: product.category || undefined,
|
||||
quantity: 1,
|
||||
quantity: selectedQuantity,
|
||||
unit_of_measure: product.unit_of_measure || 'unidad',
|
||||
unit_price: product.average_cost || product.standard_cost || 0,
|
||||
line_discount: 0
|
||||
};
|
||||
setOrderItems(items => [...items, newItem]);
|
||||
}
|
||||
setShowProductModal(false);
|
||||
|
||||
// Reset selection
|
||||
setSelectedProductId('');
|
||||
setSelectedQuantity(1);
|
||||
};
|
||||
|
||||
const handleUpdateItemQuantity = (productId: string, quantity: number) => {
|
||||
@@ -213,22 +220,6 @@ export const OrderFormModal: React.FC<OrderFormModalProps> = ({
|
||||
onClose();
|
||||
};
|
||||
|
||||
// Get unique categories for filtering
|
||||
const uniqueCategories = Array.from(new Set(
|
||||
finishedProducts
|
||||
.map(product => product.category)
|
||||
.filter(Boolean)
|
||||
)).sort();
|
||||
|
||||
const filteredProducts = finishedProducts.filter(product => {
|
||||
const matchesSearch = product.name.toLowerCase().includes(productSearch.toLowerCase()) ||
|
||||
(product.category && product.category.toLowerCase().includes(productSearch.toLowerCase())) ||
|
||||
(product.description && product.description.toLowerCase().includes(productSearch.toLowerCase()));
|
||||
|
||||
const matchesCategory = !selectedCategory || product.category === selectedCategory;
|
||||
|
||||
return matchesSearch && matchesCategory;
|
||||
});
|
||||
|
||||
// Convert form data to StatusModal sections
|
||||
const modalSections: StatusModalSection[] = [
|
||||
@@ -238,8 +229,30 @@ export const OrderFormModal: React.FC<OrderFormModalProps> = ({
|
||||
fields: [
|
||||
{
|
||||
label: 'Cliente Seleccionado',
|
||||
value: selectedCustomer ? `${selectedCustomer.name} (${selectedCustomer.customer_code})` : 'Ninguno',
|
||||
span: 2
|
||||
value: selectedCustomer ? selectedCustomer.id : '',
|
||||
type: 'select',
|
||||
editable: true,
|
||||
placeholder: 'Seleccionar cliente...',
|
||||
options: customers.map(customer => ({
|
||||
value: customer.id,
|
||||
label: `${customer.name} (${customer.customer_code})`
|
||||
})),
|
||||
span: 1
|
||||
},
|
||||
{
|
||||
label: 'Nuevo Cliente',
|
||||
value: (
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => setShowCustomerForm(true)}
|
||||
className="w-full"
|
||||
>
|
||||
<Plus className="w-4 h-4 mr-2" />
|
||||
Agregar Cliente
|
||||
</Button>
|
||||
),
|
||||
span: 1
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -281,15 +294,88 @@ export const OrderFormModal: React.FC<OrderFormModalProps> = ({
|
||||
icon: Package,
|
||||
fields: [
|
||||
{
|
||||
label: 'Total de Productos',
|
||||
value: orderItems.length,
|
||||
highlight: true
|
||||
},
|
||||
{
|
||||
label: 'Lista de Productos',
|
||||
value: orderItems.length > 0 ? orderItems.map(item => `${item.product_name} (x${item.quantity})`).join(', ') : 'Sin productos',
|
||||
label: 'Agregar Producto',
|
||||
value: (
|
||||
<div className="flex gap-3 items-end">
|
||||
<div className="flex-1">
|
||||
<select
|
||||
value={selectedProductId}
|
||||
onChange={(e) => setSelectedProductId(e.target.value)}
|
||||
className="w-full px-3 py-2 border border-[var(--border-secondary)] rounded-md focus:outline-none focus:ring-2 focus:ring-[var(--color-primary)] focus:border-transparent bg-[var(--bg-primary)]"
|
||||
>
|
||||
<option value="">Seleccionar producto...</option>
|
||||
{finishedProducts.map(product => (
|
||||
<option key={product.id} value={product.id}>
|
||||
{product.name} - €{(product.average_cost || product.standard_cost || 0).toFixed(2)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
<div className="w-24">
|
||||
<Input
|
||||
type="number"
|
||||
min="1"
|
||||
value={selectedQuantity}
|
||||
onChange={(e) => setSelectedQuantity(Number(e.target.value))}
|
||||
placeholder="Cant."
|
||||
/>
|
||||
</div>
|
||||
<Button
|
||||
onClick={handleAddSelectedProduct}
|
||||
disabled={!selectedProductId || selectedQuantity <= 0}
|
||||
className="whitespace-nowrap"
|
||||
>
|
||||
<Plus className="w-4 h-4 mr-1" />
|
||||
Agregar
|
||||
</Button>
|
||||
</div>
|
||||
),
|
||||
span: 2
|
||||
}
|
||||
},
|
||||
...(orderItems.length > 0 ? [{
|
||||
label: 'Productos en el Pedido',
|
||||
value: (
|
||||
<div className="space-y-2">
|
||||
{orderItems.map((item, index) => (
|
||||
<div key={`${item.product_id}-${index}`} className="flex items-center justify-between p-3 bg-[var(--bg-secondary)] rounded-lg">
|
||||
<div className="flex-1">
|
||||
<h4 className="font-medium text-[var(--text-primary)]">{item.product_name}</h4>
|
||||
<p className="text-sm text-[var(--text-secondary)]">
|
||||
€{item.unit_price.toFixed(2)} × {item.quantity} = €{(item.unit_price * item.quantity).toFixed(2)}
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
onClick={() => handleUpdateItemQuantity(item.product_id, item.quantity - 1)}
|
||||
disabled={item.quantity <= 1}
|
||||
>
|
||||
<Minus className="w-4 h-4" />
|
||||
</Button>
|
||||
<span className="min-w-[2rem] text-center font-medium">{item.quantity}</span>
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
onClick={() => handleUpdateItemQuantity(item.product_id, item.quantity + 1)}
|
||||
>
|
||||
<Plus className="w-4 h-4" />
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
onClick={() => handleUpdateItemQuantity(item.product_id, 0)}
|
||||
className="text-red-600 hover:text-red-700 ml-2"
|
||||
>
|
||||
<X className="w-4 h-4" />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
),
|
||||
span: 2
|
||||
}] : [])
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -334,7 +420,12 @@ export const OrderFormModal: React.FC<OrderFormModalProps> = ({
|
||||
const field = section.fields[fieldIndex];
|
||||
|
||||
// Update order data based on field changes
|
||||
if (section.title === 'Detalles del Pedido') {
|
||||
if (section.title === 'Cliente') {
|
||||
if (field.label === 'Cliente Seleccionado') {
|
||||
const customer = customers.find(c => c.id === value);
|
||||
setSelectedCustomer(customer || null);
|
||||
}
|
||||
} else if (section.title === 'Detalles del Pedido') {
|
||||
if (field.label === 'Tipo de Pedido') {
|
||||
setOrderData(prev => ({ ...prev, order_type: value as OrderType }));
|
||||
} else if (field.label === 'Prioridad') {
|
||||
@@ -361,17 +452,6 @@ export const OrderFormModal: React.FC<OrderFormModalProps> = ({
|
||||
size="2xl"
|
||||
showDefaultActions={false}
|
||||
actions={[
|
||||
{
|
||||
label: selectedCustomer ? 'Cambiar Cliente' : 'Seleccionar Cliente',
|
||||
variant: 'outline',
|
||||
onClick: () => setShowCustomerSelector(true)
|
||||
},
|
||||
{
|
||||
label: 'Agregar Productos',
|
||||
variant: 'outline',
|
||||
onClick: () => setShowProductModal(true),
|
||||
icon: Plus
|
||||
},
|
||||
{
|
||||
label: 'Cancelar',
|
||||
variant: 'outline',
|
||||
@@ -392,118 +472,6 @@ export const OrderFormModal: React.FC<OrderFormModalProps> = ({
|
||||
|
||||
</div>
|
||||
|
||||
{/* Product Selection Modal - Using StatusModal for consistency */}
|
||||
<StatusModal
|
||||
isOpen={showProductModal}
|
||||
onClose={() => setShowProductModal(false)}
|
||||
mode="view"
|
||||
title="Seleccionar Productos"
|
||||
subtitle="Elija productos terminados para agregar al pedido"
|
||||
size="2xl"
|
||||
showDefaultActions={false}
|
||||
sections={[
|
||||
{
|
||||
title: 'Filtros',
|
||||
icon: Package,
|
||||
fields: [
|
||||
{
|
||||
label: 'Buscar productos',
|
||||
value: productSearch,
|
||||
type: 'text',
|
||||
editable: true,
|
||||
placeholder: 'Buscar productos...',
|
||||
span: 1
|
||||
},
|
||||
{
|
||||
label: 'Categoría',
|
||||
value: selectedCategory,
|
||||
type: 'select',
|
||||
editable: true,
|
||||
placeholder: 'Todas las categorías',
|
||||
options: [
|
||||
{ value: '', label: 'Todas las categorías' },
|
||||
...uniqueCategories.map(category => ({
|
||||
value: category,
|
||||
label: category
|
||||
}))
|
||||
],
|
||||
span: 1
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: 'Productos Disponibles',
|
||||
icon: ShoppingCart,
|
||||
fields: [
|
||||
{
|
||||
label: 'Lista de productos',
|
||||
value: (
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 max-h-96 overflow-y-auto">
|
||||
{productsLoading ? (
|
||||
<div className="col-span-2 text-center py-8">
|
||||
<p className="text-[var(--text-secondary)]">Cargando productos...</p>
|
||||
</div>
|
||||
) : filteredProducts.length === 0 ? (
|
||||
<div className="col-span-2 text-center py-8">
|
||||
<p className="text-[var(--text-secondary)]">
|
||||
{productSearch ? 'No se encontraron productos que coincidan con la búsqueda' : 'No hay productos finalizados disponibles'}
|
||||
</p>
|
||||
</div>
|
||||
) : (
|
||||
filteredProducts.map(product => (
|
||||
<div key={product.id} className="border border-[var(--border-primary)] rounded-lg p-4 hover:bg-[var(--bg-secondary)]">
|
||||
<div className="flex items-start justify-between">
|
||||
<div className="flex-1">
|
||||
<h4 className="font-medium text-[var(--text-primary)]">{product.name}</h4>
|
||||
{product.description && (
|
||||
<p className="text-sm text-[var(--text-secondary)] mt-1">{product.description}</p>
|
||||
)}
|
||||
<div className="flex items-center mt-2 flex-wrap gap-2">
|
||||
{product.category && (
|
||||
<Badge variant="soft" color="gray">
|
||||
{product.category}
|
||||
</Badge>
|
||||
)}
|
||||
<span className="text-lg font-semibold text-[var(--color-info)]">
|
||||
€{(product.average_cost || product.standard_cost || 0).toFixed(2)}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Button
|
||||
size="sm"
|
||||
onClick={() => handleAddProduct(product)}
|
||||
disabled={!product.is_active || (product.total_quantity || 0) <= 0}
|
||||
>
|
||||
<Plus className="w-4 h-4 mr-1" />
|
||||
Agregar
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="text-xs text-[var(--text-tertiary)] mt-2 flex justify-between">
|
||||
<span>Stock: {product.total_quantity || 0} {product.unit_of_measure}</span>
|
||||
{product.sku && <span>SKU: {product.sku}</span>}
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
)}
|
||||
</div>
|
||||
),
|
||||
span: 2
|
||||
}
|
||||
]
|
||||
}
|
||||
]}
|
||||
onFieldChange={(sectionIndex, fieldIndex, value) => {
|
||||
if (sectionIndex === 0) {
|
||||
if (fieldIndex === 0) {
|
||||
setProductSearch(String(value));
|
||||
} else if (fieldIndex === 1) {
|
||||
setSelectedCategory(String(value));
|
||||
}
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* New Customer Modal - Using StatusModal for consistency */}
|
||||
<StatusModal
|
||||
|
||||
@@ -17,6 +17,7 @@ import {
|
||||
Truck,
|
||||
Zap,
|
||||
Database,
|
||||
Store,
|
||||
GraduationCap,
|
||||
Bell,
|
||||
Settings,
|
||||
@@ -93,6 +94,7 @@ const iconMap: Record<string, React.ComponentType<{ className?: string }>> = {
|
||||
procurement: Truck,
|
||||
pos: Zap,
|
||||
data: Database,
|
||||
database: Store,
|
||||
training: GraduationCap,
|
||||
notifications: Bell,
|
||||
settings: Settings,
|
||||
|
||||
97
frontend/src/pages/app/database/DatabasePage.tsx
Normal file
97
frontend/src/pages/app/database/DatabasePage.tsx
Normal file
@@ -0,0 +1,97 @@
|
||||
import React from 'react';
|
||||
import { Outlet, useLocation } from 'react-router-dom';
|
||||
import { PageHeader } from '../../../components/layout/PageHeader/PageHeader';
|
||||
import { Database, Package, ShoppingCart, Truck, Settings, Users, MessageSquare } from 'lucide-react';
|
||||
|
||||
const DatabasePage: React.FC = () => {
|
||||
const location = useLocation();
|
||||
const isParentRoute = location.pathname === '/app/database';
|
||||
|
||||
if (!isParentRoute) {
|
||||
return <Outlet />;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="p-6 space-y-6">
|
||||
<PageHeader
|
||||
title="Mi Panadería"
|
||||
description="Consulta y gestiona toda la información de tu panadería"
|
||||
/>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
<div className="bg-white rounded-lg border border-gray-200 p-6 hover:shadow-md transition-shadow cursor-pointer">
|
||||
<div className="flex items-center space-x-3 mb-4">
|
||||
<div className="p-2 bg-blue-100 rounded-lg">
|
||||
<Package className="w-6 h-6 text-blue-600" />
|
||||
</div>
|
||||
<h3 className="text-lg font-semibold text-gray-900">Recetas</h3>
|
||||
</div>
|
||||
<p className="text-gray-600">Gestiona las recetas de tus productos</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-white rounded-lg border border-gray-200 p-6 hover:shadow-md transition-shadow cursor-pointer">
|
||||
<div className="flex items-center space-x-3 mb-4">
|
||||
<div className="p-2 bg-green-100 rounded-lg">
|
||||
<ShoppingCart className="w-6 h-6 text-green-600" />
|
||||
</div>
|
||||
<h3 className="text-lg font-semibold text-gray-900">Pedidos</h3>
|
||||
</div>
|
||||
<p className="text-gray-600">Consulta el estado de todos los pedidos</p>
|
||||
</div>
|
||||
|
||||
|
||||
<div className="bg-white rounded-lg border border-gray-200 p-6 hover:shadow-md transition-shadow cursor-pointer">
|
||||
<div className="flex items-center space-x-3 mb-4">
|
||||
<div className="p-2 bg-yellow-100 rounded-lg">
|
||||
<Truck className="w-6 h-6 text-yellow-600" />
|
||||
</div>
|
||||
<h3 className="text-lg font-semibold text-gray-900">Proveedores</h3>
|
||||
</div>
|
||||
<p className="text-gray-600">Gestiona tus proveedores</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-white rounded-lg border border-gray-200 p-6 hover:shadow-md transition-shadow cursor-pointer">
|
||||
<div className="flex items-center space-x-3 mb-4">
|
||||
<div className="p-2 bg-red-100 rounded-lg">
|
||||
<Database className="w-6 h-6 text-red-600" />
|
||||
</div>
|
||||
<h3 className="text-lg font-semibold text-gray-900">Inventario</h3>
|
||||
</div>
|
||||
<p className="text-gray-600">Estado actual del inventario</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-white rounded-lg border border-gray-200 p-6 hover:shadow-md transition-shadow cursor-pointer">
|
||||
<div className="flex items-center space-x-3 mb-4">
|
||||
<div className="p-2 bg-indigo-100 rounded-lg">
|
||||
<Settings className="w-6 h-6 text-indigo-600" />
|
||||
</div>
|
||||
<h3 className="text-lg font-semibold text-gray-900">Configuración de Panadería</h3>
|
||||
</div>
|
||||
<p className="text-gray-600">Configuración general de tu panadería</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-white rounded-lg border border-gray-200 p-6 hover:shadow-md transition-shadow cursor-pointer">
|
||||
<div className="flex items-center space-x-3 mb-4">
|
||||
<div className="p-2 bg-orange-100 rounded-lg">
|
||||
<Users className="w-6 h-6 text-orange-600" />
|
||||
</div>
|
||||
<h3 className="text-lg font-semibold text-gray-900">Gestión de Equipo</h3>
|
||||
</div>
|
||||
<p className="text-gray-600">Administra tu equipo de trabajo</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-white rounded-lg border border-gray-200 p-6 hover:shadow-md transition-shadow cursor-pointer">
|
||||
<div className="flex items-center space-x-3 mb-4">
|
||||
<div className="p-2 bg-teal-100 rounded-lg">
|
||||
<MessageSquare className="w-6 h-6 text-teal-600" />
|
||||
</div>
|
||||
<h3 className="text-lg font-semibold text-gray-900">Preferencias de Comunicación</h3>
|
||||
</div>
|
||||
<p className="text-gray-600">Configura notificaciones y comunicaciones</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default DatabasePage;
|
||||
@@ -33,6 +33,9 @@ const BakeryConfigPage = React.lazy(() => import('../pages/app/settings/bakery-c
|
||||
const TeamPage = React.lazy(() => import('../pages/app/settings/team/TeamPage'));
|
||||
const SubscriptionPage = React.lazy(() => import('../pages/app/settings/subscription/SubscriptionPage'));
|
||||
|
||||
// Database pages
|
||||
const DatabasePage = React.lazy(() => import('../pages/app/database/DatabasePage'));
|
||||
|
||||
// Data pages
|
||||
const WeatherPage = React.lazy(() => import('../pages/app/data/weather/WeatherPage'));
|
||||
const TrafficPage = React.lazy(() => import('../pages/app/data/traffic/TrafficPage'));
|
||||
@@ -72,76 +75,118 @@ export const AppRouter: React.FC = () => {
|
||||
}
|
||||
/>
|
||||
|
||||
{/* Operations Routes */}
|
||||
<Route
|
||||
path="/app/operations/inventory"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<AppShell>
|
||||
<InventoryPage />
|
||||
</AppShell>
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/app/operations/production"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<AppShell>
|
||||
<ProductionPage />
|
||||
</AppShell>
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/app/operations/recipes"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<AppShell>
|
||||
<RecipesPage />
|
||||
</AppShell>
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/app/operations/procurement"
|
||||
{/* Operations Routes - Business Operations Only */}
|
||||
<Route
|
||||
path="/app/operations/procurement"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<AppShell>
|
||||
<ProcurementPage />
|
||||
</AppShell>
|
||||
</ProtectedRoute>
|
||||
}
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/app/operations/suppliers"
|
||||
<Route
|
||||
path="/app/operations/production"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<AppShell>
|
||||
<SuppliersPage />
|
||||
<ProductionPage />
|
||||
</AppShell>
|
||||
</ProtectedRoute>
|
||||
}
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/app/operations/orders"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<AppShell>
|
||||
<OrdersPage />
|
||||
</AppShell>
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/app/operations/pos"
|
||||
<Route
|
||||
path="/app/operations/pos"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<AppShell>
|
||||
<POSPage />
|
||||
</AppShell>
|
||||
</ProtectedRoute>
|
||||
}
|
||||
}
|
||||
/>
|
||||
|
||||
{/* Database Routes - Current Bakery Status */}
|
||||
<Route
|
||||
path="/app/database"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<AppShell>
|
||||
<DatabasePage />
|
||||
</AppShell>
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/app/database/recipes"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<AppShell>
|
||||
<RecipesPage />
|
||||
</AppShell>
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/app/database/orders"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<AppShell>
|
||||
<OrdersPage />
|
||||
</AppShell>
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/app/database/suppliers"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<AppShell>
|
||||
<SuppliersPage />
|
||||
</AppShell>
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/app/database/inventory"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<AppShell>
|
||||
<InventoryPage />
|
||||
</AppShell>
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/app/database/bakery-config"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<AppShell>
|
||||
<BakeryConfigPage />
|
||||
</AppShell>
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/app/database/team"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<AppShell>
|
||||
<TeamPage />
|
||||
</AppShell>
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/app/database/preferences"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<AppShell>
|
||||
<PreferencesPage />
|
||||
</AppShell>
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
|
||||
{/* Analytics Routes */}
|
||||
@@ -187,18 +232,6 @@ export const AppRouter: React.FC = () => {
|
||||
/>
|
||||
|
||||
|
||||
{/* Settings Routes */}
|
||||
<Route
|
||||
path="/app/settings/preferences"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<AppShell>
|
||||
<PreferencesPage />
|
||||
</AppShell>
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
|
||||
{/* Settings Routes */}
|
||||
<Route
|
||||
path="/app/settings/profile"
|
||||
@@ -210,26 +243,6 @@ export const AppRouter: React.FC = () => {
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/app/settings/bakery-config"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<AppShell>
|
||||
<BakeryConfigPage />
|
||||
</AppShell>
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/app/settings/team"
|
||||
element={
|
||||
<ProtectedRoute>
|
||||
<AppShell>
|
||||
<TeamPage />
|
||||
</AppShell>
|
||||
</ProtectedRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/app/settings/subscription"
|
||||
element={
|
||||
|
||||
@@ -44,14 +44,14 @@ export const ROUTES = {
|
||||
DASHBOARD: '/app/dashboard',
|
||||
|
||||
// Inventory Management
|
||||
INVENTORY: '/app/operations/inventory',
|
||||
INVENTORY: '/app/database/inventory',
|
||||
INVENTORY_INGREDIENTS: '/inventory/ingredients',
|
||||
INVENTORY_STOCK: '/inventory/stock',
|
||||
INVENTORY_MOVEMENTS: '/inventory/movements',
|
||||
INVENTORY_ALERTS: '/inventory/alerts',
|
||||
INVENTORY_QUALITY: '/inventory/quality',
|
||||
INVENTORY_REPORTS: '/inventory/reports',
|
||||
|
||||
|
||||
// Production Management
|
||||
PRODUCTION: '/app/operations/production',
|
||||
PRODUCTION_BATCHES: '/production/batches',
|
||||
@@ -75,33 +75,41 @@ export const ROUTES = {
|
||||
FORECASTING_ANALYTICS: '/forecasting/analytics',
|
||||
|
||||
// Orders Management
|
||||
ORDERS: '/orders',
|
||||
ORDERS: '/app/database/orders',
|
||||
ORDERS_LIST: '/orders/list',
|
||||
ORDERS_QUEUE: '/orders/queue',
|
||||
ORDERS_HISTORY: '/orders/history',
|
||||
ORDERS_CUSTOMERS: '/orders/customers',
|
||||
|
||||
|
||||
// Procurement
|
||||
PROCUREMENT: '/procurement',
|
||||
PROCUREMENT: '/app/operations/procurement',
|
||||
PROCUREMENT_ORDERS: '/procurement/orders',
|
||||
PROCUREMENT_SUPPLIERS: '/procurement/suppliers',
|
||||
PROCUREMENT_DELIVERIES: '/procurement/deliveries',
|
||||
PROCUREMENT_ANALYTICS: '/procurement/analytics',
|
||||
|
||||
// Recipes
|
||||
RECIPES: '/app/database/recipes',
|
||||
|
||||
// Suppliers
|
||||
SUPPLIERS: '/app/database/suppliers',
|
||||
|
||||
|
||||
// Point of Sale
|
||||
POS: '/pos',
|
||||
POS: '/app/operations/pos',
|
||||
POS_INTEGRATION: '/pos/integration',
|
||||
POS_TRANSACTIONS: '/pos/transactions',
|
||||
POS_WEBHOOKS: '/pos/webhooks',
|
||||
POS_SETTINGS: '/pos/settings',
|
||||
|
||||
// Data Management
|
||||
DATA: '/data',
|
||||
DATA: '/app/data',
|
||||
DATA_IMPORT: '/data/import',
|
||||
DATA_EXPORT: '/data/export',
|
||||
DATA_EXTERNAL: '/data/external',
|
||||
DATA_WEATHER: '/data/weather',
|
||||
DATA_EVENTS: '/data/events',
|
||||
DATA_WEATHER: '/app/data/weather',
|
||||
DATA_EVENTS: '/app/data/events',
|
||||
DATA_TRAFFIC: '/app/data/traffic',
|
||||
|
||||
// Training & ML
|
||||
TRAINING: '/training',
|
||||
@@ -118,14 +126,16 @@ export const ROUTES = {
|
||||
|
||||
// Settings
|
||||
SETTINGS: '/settings',
|
||||
SETTINGS_PROFILE: '/settings/profile',
|
||||
SETTINGS_PROFILE: '/app/settings/profile',
|
||||
SETTINGS_TENANT: '/settings/tenant',
|
||||
SETTINGS_USERS: '/settings/users',
|
||||
SETTINGS_PERMISSIONS: '/settings/permissions',
|
||||
SETTINGS_INTEGRATIONS: '/settings/integrations',
|
||||
SETTINGS_PREFERENCES: '/settings/preferences',
|
||||
SETTINGS_PREFERENCES: '/app/database/preferences',
|
||||
SETTINGS_BILLING: '/settings/billing',
|
||||
SETTINGS_SUBSCRIPTION: '/app/settings/subscription',
|
||||
SETTINGS_BAKERY_CONFIG: '/app/database/bakery-config',
|
||||
SETTINGS_TEAM: '/app/database/team',
|
||||
|
||||
// Reports
|
||||
REPORTS: '/reports',
|
||||
@@ -207,7 +217,7 @@ export const routesConfig: RouteConfig[] = [
|
||||
},
|
||||
},
|
||||
|
||||
// Operations Section
|
||||
// Operations Section - Business Operations Only
|
||||
{
|
||||
path: '/app/operations',
|
||||
name: 'Operations',
|
||||
@@ -217,46 +227,6 @@ export const routesConfig: RouteConfig[] = [
|
||||
requiresAuth: true,
|
||||
showInNavigation: true,
|
||||
children: [
|
||||
{
|
||||
path: '/app/operations/production',
|
||||
name: 'Production',
|
||||
component: 'ProductionPage',
|
||||
title: 'Producción',
|
||||
icon: 'production',
|
||||
requiresAuth: true,
|
||||
showInNavigation: true,
|
||||
showInBreadcrumbs: true,
|
||||
},
|
||||
{
|
||||
path: '/app/operations/orders',
|
||||
name: 'Orders',
|
||||
component: 'OrdersPage',
|
||||
title: 'Pedidos',
|
||||
icon: 'orders',
|
||||
requiresAuth: true,
|
||||
showInNavigation: true,
|
||||
showInBreadcrumbs: true,
|
||||
},
|
||||
{
|
||||
path: '/app/operations/inventory',
|
||||
name: 'Inventory',
|
||||
component: 'InventoryPage',
|
||||
title: 'Inventario',
|
||||
icon: 'inventory',
|
||||
requiresAuth: true,
|
||||
showInNavigation: true,
|
||||
showInBreadcrumbs: true,
|
||||
},
|
||||
{
|
||||
path: '/app/operations/recipes',
|
||||
name: 'Recipes',
|
||||
component: 'RecipesPage',
|
||||
title: 'Recetas',
|
||||
icon: 'production',
|
||||
requiresAuth: true,
|
||||
showInNavigation: true,
|
||||
showInBreadcrumbs: true,
|
||||
},
|
||||
{
|
||||
path: '/app/operations/procurement',
|
||||
name: 'Procurement',
|
||||
@@ -268,11 +238,11 @@ export const routesConfig: RouteConfig[] = [
|
||||
showInBreadcrumbs: true,
|
||||
},
|
||||
{
|
||||
path: '/app/operations/suppliers',
|
||||
name: 'Suppliers',
|
||||
component: 'SuppliersPage',
|
||||
title: 'Proveedores',
|
||||
icon: 'procurement',
|
||||
path: '/app/operations/production',
|
||||
name: 'Production',
|
||||
component: 'ProductionPage',
|
||||
title: 'Producción',
|
||||
icon: 'production',
|
||||
requiresAuth: true,
|
||||
showInNavigation: true,
|
||||
showInBreadcrumbs: true,
|
||||
@@ -290,6 +260,91 @@ export const routesConfig: RouteConfig[] = [
|
||||
],
|
||||
},
|
||||
|
||||
// Catalog Section - Current Bakery Status
|
||||
{
|
||||
path: '/app/database',
|
||||
name: 'Database',
|
||||
component: 'DatabasePage',
|
||||
title: 'Mi Panadería',
|
||||
icon: 'database',
|
||||
requiresAuth: true,
|
||||
showInNavigation: true,
|
||||
children: [
|
||||
{
|
||||
path: '/app/database/recipes',
|
||||
name: 'Recipes',
|
||||
component: 'RecipesPage',
|
||||
title: 'Recetas',
|
||||
icon: 'production',
|
||||
requiresAuth: true,
|
||||
showInNavigation: true,
|
||||
showInBreadcrumbs: true,
|
||||
},
|
||||
{
|
||||
path: '/app/database/orders',
|
||||
name: 'Orders',
|
||||
component: 'OrdersPage',
|
||||
title: 'Pedidos',
|
||||
icon: 'orders',
|
||||
requiresAuth: true,
|
||||
showInNavigation: true,
|
||||
showInBreadcrumbs: true,
|
||||
},
|
||||
{
|
||||
path: '/app/database/suppliers',
|
||||
name: 'Suppliers',
|
||||
component: 'SuppliersPage',
|
||||
title: 'Proveedores',
|
||||
icon: 'procurement',
|
||||
requiresAuth: true,
|
||||
showInNavigation: true,
|
||||
showInBreadcrumbs: true,
|
||||
},
|
||||
{
|
||||
path: '/app/database/inventory',
|
||||
name: 'Inventory',
|
||||
component: 'InventoryPage',
|
||||
title: 'Inventario',
|
||||
icon: 'inventory',
|
||||
requiresAuth: true,
|
||||
showInNavigation: true,
|
||||
showInBreadcrumbs: true,
|
||||
},
|
||||
{
|
||||
path: '/app/database/bakery-config',
|
||||
name: 'BakeryConfig',
|
||||
component: 'BakeryConfigPage',
|
||||
title: 'Configuración de Panadería',
|
||||
icon: 'settings',
|
||||
requiresAuth: true,
|
||||
requiredRoles: ROLE_COMBINATIONS.ADMIN_ACCESS,
|
||||
showInNavigation: true,
|
||||
showInBreadcrumbs: true,
|
||||
},
|
||||
{
|
||||
path: '/app/database/team',
|
||||
name: 'Team',
|
||||
component: 'TeamPage',
|
||||
title: 'Gestión de Equipo',
|
||||
icon: 'user',
|
||||
requiresAuth: true,
|
||||
requiredRoles: ROLE_COMBINATIONS.ADMIN_ACCESS,
|
||||
showInNavigation: true,
|
||||
showInBreadcrumbs: true,
|
||||
},
|
||||
{
|
||||
path: '/app/database/preferences',
|
||||
name: 'CommunicationPreferences',
|
||||
component: 'PreferencesPage',
|
||||
title: 'Preferencias de Comunicación',
|
||||
icon: 'settings',
|
||||
requiresAuth: true,
|
||||
showInNavigation: true,
|
||||
showInBreadcrumbs: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// Analytics Section
|
||||
{
|
||||
path: '/app/analytics',
|
||||
@@ -368,28 +423,6 @@ export const routesConfig: RouteConfig[] = [
|
||||
showInNavigation: true,
|
||||
showInBreadcrumbs: true,
|
||||
},
|
||||
{
|
||||
path: '/app/settings/bakery-config',
|
||||
name: 'BakeryConfig',
|
||||
component: 'BakeryConfigPage',
|
||||
title: 'Configuración de Panadería',
|
||||
icon: 'settings',
|
||||
requiresAuth: true,
|
||||
requiredRoles: ROLE_COMBINATIONS.ADMIN_ACCESS,
|
||||
showInNavigation: true,
|
||||
showInBreadcrumbs: true,
|
||||
},
|
||||
{
|
||||
path: '/app/settings/team',
|
||||
name: 'Team',
|
||||
component: 'TeamPage',
|
||||
title: 'Gestión de Equipo',
|
||||
icon: 'settings',
|
||||
requiresAuth: true,
|
||||
requiredRoles: ROLE_COMBINATIONS.ADMIN_ACCESS,
|
||||
showInNavigation: true,
|
||||
showInBreadcrumbs: true,
|
||||
},
|
||||
{
|
||||
path: '/app/settings/subscription',
|
||||
name: 'Subscription',
|
||||
@@ -401,16 +434,6 @@ export const routesConfig: RouteConfig[] = [
|
||||
showInNavigation: true,
|
||||
showInBreadcrumbs: true,
|
||||
},
|
||||
{
|
||||
path: '/app/settings/preferences',
|
||||
name: 'CommunicationPreferences',
|
||||
component: 'PreferencesPage',
|
||||
title: 'Preferencias de Comunicación',
|
||||
icon: 'settings',
|
||||
requiresAuth: true,
|
||||
showInNavigation: true,
|
||||
showInBreadcrumbs: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
|
||||
Reference in New Issue
Block a user