from nicegui import ui import api_client from pages.logistics import render_logistics_page # Define the layout @ui.page('/') def main_page(): with ui.header().classes('items-center justify-between'): ui.label('Suite de Producción de Ballet').classes('text-2xl font-bold') with ui.row(): ui.button('Cerrar Sesión', icon='logout', on_click=lambda: ui.notify('Sesión cerrada')) with ui.left_drawer(value=True).classes('bg-slate-100'): with ui.column().classes('w-full gap-2 p-4'): ui.button('Panel de Control', icon='dashboard', on_click=lambda: content.set_content('Dashboard')).classes('w-full justify-start') ui.button('Productos', icon='inventory_2', on_click=lambda: content.set_content('Productos')).classes('w-full justify-start') ui.button('CRM y Pedidos', icon='people', on_click=lambda: content.set_content('CRM')).classes('w-full justify-start') ui.button('Producción', icon='factory', on_click=lambda: content.set_content('Producción')).classes('w-full justify-start') ui.button('Inventario', icon='category', on_click=lambda: content.set_content('Inventario')).classes('w-full justify-start') ui.button('Logística', icon='local_shipping', on_click=lambda: content.set_content('Logística')).classes('w-full justify-start') with ui.column().classes('w-full p-8') as main_content: ui.label('Bienvenido al Panel de Control de Ballet Atelier').classes('text-3xl') ui.markdown(''' Gestione su negocio de ropa de ballet de manera eficiente: - **Productos**: Seguimiento de sus más de 100 modelos y materiales. - **CRM**: Gestione clientes y sus medidas únicas. - **Producción**: Supervise los pedidos a través del flujo del taller. - **Inventario**: Seguimiento de stock y alertas en tiempo real. ''') class ContentManager: def set_content(self, page_name): main_content.clear() with main_content: ui.label(f'Página de {page_name}').classes('text-3xl mb-4') if page_name == 'Dashboard': ui.label('Aquí aparecerán las estadísticas resumidas.') elif page_name == 'Inventario': render_inventory_page() elif page_name == 'CRM': render_crm_page() elif page_name == 'Producción': render_production_page() elif page_name == 'Logística': render_logistics_page() elif page_name == 'Productos': render_products_page() else: ui.label(f'Contenido para {page_name} próximamente...').classes('text-xl') content = ContentManager() def render_crm_page(): ui.label('Gestión de Clientes (CRM)').classes('text-xl mb-4') with ui.row().classes('w-full items-start gap-4'): # Client List with ui.card().classes('flex-1'): ui.label('Clientes').classes('font-bold mb-2') columns = [ {'name': 'name', 'label': 'Nombre', 'field': 'name', 'align': 'left'}, {'name': 'phone', 'label': 'Teléfono', 'field': 'phone'}, ] rows = [ {'name': 'Maria Garcia', 'phone': '600-000-000'}, {'name': 'Elena Rodriguez', 'phone': '611-111-111'}, ] ui.table(columns=columns, rows=rows, row_key='name').classes('w-full') # New Client Form with ui.card().classes('w-64'): ui.label('Nuevo Cliente').classes('font-bold') ui.input('Nombre Completo') ui.input('Teléfono') ui.textarea('Medidas').classes('w-full') ui.button('Guardar Cliente', on_click=lambda: ui.notify('Cliente guardado')) def render_production_page(): ui.label('Flujo de Producción (Kanban)').classes('text-xl mb-4') with ui.row().classes('w-full mb-4'): ui.button('Generar Hoja de Corte', icon='content_cut', on_click=lambda: ui.notify('Hoja de corte generada para todos los pedidos pendientes')) with ui.row().classes('w-full justify-between gap-4'): for status_label in ['Corte', 'Confección', 'Terminado']: with ui.column().classes('bg-slate-50 p-4 rounded-lg flex-1 min-h-[400px] border border-slate-200'): ui.label(status_label).classes('font-bold text-lg mb-4 text-slate-600 uppercase tracking-wider') # Sample Card with ui.card().classes('w-full mb-2 cursor-pointer hover:shadow-md transition-shadow'): ui.label('Pedido #1001').classes('font-bold') ui.label('Cliente: Maria Garcia') ui.label('Estado: En Proceso').classes('text-xs text-blue-500') with ui.row().classes('justify-end w-full'): ui.button(icon='arrow_forward', variant='text').classes('p-0') def render_products_page(): ui.label('Catálogo de Productos').classes('text-xl mb-4') with ui.grid(columns=3).classes('w-full gap-4'): # In a real app, this would fetch from the API products = [ {'name': 'Tutú Profesional', 'sku': 'TUTU-001', 'total_cost': 65.50}, {'name': 'Maillot Clásico', 'sku': 'LEO-002', 'total_cost': 28.00}, {'name': 'Falda de Ballet', 'sku': 'SKT-003', 'total_cost': 15.20}, ] for p in products: with ui.card(): ui.label(p['name']).classes('font-bold') ui.label(f"SKU: {p['sku']}").classes('text-xs text-slate-500') ui.label(f"Coste Total: {p['total_cost']}€").classes('text-lg font-semibold text-primary') ui.button('Editar Materiales', variant='text') def render_inventory_page(): ui.label('Inventario de Materiales').classes('text-xl mb-2') # Simple form to add material with ui.card().classes('w-full mb-4'): ui.label('Añadir Nuevo Material').classes('font-bold') with ui.row(): name = ui.input('Nombre') unit = ui.input('Unidad (ej. metros)') stock = ui.number('Stock Inicial', value=0) cost = ui.number('Coste por Unidad', value=0.0) ui.button('Añadir Material', on_click=lambda: ui.notify(f'Añadido {name.value}')) # Placeholder for table ui.label('Niveles de Stock').classes('font-bold') columns = [ {'name': 'name', 'label': 'Nombre', 'field': 'name', 'required': True, 'align': 'left'}, {'name': 'unit', 'label': 'Unidad', 'field': 'unit'}, {'name': 'stock', 'label': 'Stock', 'field': 'stock'}, {'name': 'cost', 'label': 'Coste', 'field': 'cost'}, ] rows = [ {'name': 'Satén Rosa', 'unit': 'metros', 'stock': 50, 'cost': 12.5}, {'name': 'Tul Blanco', 'unit': 'metros', 'stock': 120, 'cost': 5.0}, ] ui.table(columns=columns, rows=rows, row_key='name') ui.run(title="Suite de Producción de Ballet", port=8080, host='0.0.0.0')