142 lines
7.0 KiB
Python
142 lines
7.0 KiB
Python
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)
|