from nicegui import ui from services.api_client import APIClient import asyncio from typing import List, Dict, Any, Optional class PietanzePage: def __init__(self, api_client: APIClient): self.api_client = api_client self.pietanze_data = [] self.search_filter = "" self.allergen_filter = [] self.selected_pietanza = None # Available allergens self.available_allergens = [ 'glutine', 'lattosio', 'uova', 'pesce', 'crostacei', 'arachidi', 'frutta_a_guscio', 'soia', 'sedano', 'senape', 'sesamo', 'solfiti' ] def render(self): """Render pietanze management page""" ui.label('Gestione Pietanze').classes('text-3xl font-bold text-gray-800 mb-6') # Toolbar with ui.row().classes('w-full justify-between items-center mb-6'): with ui.row().classes('gap-4 items-center'): # Search input search_input = ui.input('Cerca pietanze...', on_change=self._on_search_change).classes('w-64') search_input.bind_value(self, 'search_filter') # Allergen filter with ui.select( self.available_allergens, multiple=True, label='Filtra per allergeni', on_change=self._on_filter_change ).classes('w-48') as allergen_select: allergen_select.bind_value(self, 'allergen_filter') # Refresh button ui.button('Aggiorna', icon='refresh', on_click=self._load_pietanze).props('outline') # Add new button ui.button('Nuova Pietanza', icon='add', on_click=self._show_create_dialog).classes('bg-green-600 hover:bg-green-700') # Pietanze table self._render_pietanze_table() # Load initial data asyncio.create_task(self._load_pietanze()) def _render_pietanze_table(self): """Render pietanze data table""" columns = [ {'name': 'id', 'label': 'ID', 'field': 'id', 'sortable': True}, {'name': 'nome', 'label': 'Nome', 'field': 'nome', 'sortable': True, 'align': 'left'}, {'name': 'descrizione', 'label': 'Descrizione', 'field': 'descrizione', 'align': 'left'}, {'name': 'allergeni', 'label': 'Allergeni', 'field': 'allergeni_display'}, {'name': 'actions', 'label': 'Azioni', 'field': 'actions'}, ] self.pietanze_table = ui.table( columns=columns, rows=[], row_key='id' ).classes('w-full') # Add action buttons to each row self.pietanze_table.add_slot('body-cell-actions', ''' ''') self.pietanze_table.on('edit', self._show_edit_dialog) self.pietanze_table.on('delete', self._show_delete_dialog) def _show_create_dialog(self): """Show create pietanza dialog""" self.selected_pietanza = None self._show_pietanza_dialog() def _show_edit_dialog(self, e): """Show edit pietanza dialog""" self.selected_pietanza = e.args self._show_pietanza_dialog() def _show_pietanza_dialog(self): """Show pietanza create/edit dialog""" is_edit = self.selected_pietanza is not None title = 'Modifica Pietanza' if is_edit else 'Nuova Pietanza' with ui.dialog() as dialog, ui.card().classes('w-96'): ui.label(title).classes('text-xl font-bold mb-4') # Form fields nome_input = ui.input('Nome', placeholder='Nome della pietanza').classes('w-full') descrizione_input = ui.textarea('Descrizione', placeholder='Descrizione dettagliata').classes('w-full') allergeni_select = ui.select( self.available_allergens, multiple=True, label='Allergeni' ).classes('w-full') # Pre-fill form if editing if is_edit: nome_input.value = self.selected_pietanza['nome'] descrizione_input.value = self.selected_pietanza.get('descrizione', '') allergeni_select.value = self.selected_pietanza.get('allergeni', []) # Action buttons with ui.row().classes('w-full justify-end gap-2 mt-4'): ui.button('Annulla', on_click=dialog.close).props('flat') save_btn = ui.button( 'Salva' if is_edit else 'Crea', on_click=lambda: self._save_pietanza( dialog, nome_input.value, descrizione_input.value, allergeni_select.value, is_edit ) ).classes('bg-green-600 hover:bg-green-700') dialog.open() def _show_delete_dialog(self, e): """Show delete confirmation dialog""" pietanza = e.args with ui.dialog() as dialog, ui.card(): ui.label('Conferma Eliminazione').classes('text-xl font-bold mb-4') ui.label(f'Sei sicuro di voler eliminare "{pietanza["nome"]}"?').classes('mb-4') with ui.row().classes('w-full justify-end gap-2'): ui.button('Annulla', on_click=dialog.close).props('flat') ui.button( 'Elimina', on_click=lambda: self._delete_pietanza(dialog, pietanza['id']) ).classes('bg-red-600 hover:bg-red-700') dialog.open() async def _save_pietanza(self, dialog, nome: str, descrizione: str, allergeni: List[str], is_edit: bool): """Save pietanza (create or update)""" if not nome.strip(): ui.notify('Il nome รจ obbligatorio', type='negative') return try: pietanza_data = { 'nome': nome.strip(), 'descrizione': descrizione.strip() if descrizione else None, 'allergeni': allergeni or [] } if is_edit: await self.api_client.update_pietanza(self.selected_pietanza['id'], pietanza_data) ui.notify('Pietanza aggiornata con successo', type='positive') else: await self.api_client.create_pietanza(pietanza_data) ui.notify('Pietanza creata con successo', type='positive') dialog.close() await self._load_pietanze() except Exception as e: ui.notify(f'Errore nel salvataggio: {str(e)}', type='negative') async def _delete_pietanza(self, dialog, pietanza_id: int): """Delete pietanza""" try: await self.api_client.delete_pietanza(pietanza_id) ui.notify('Pietanza eliminata con successo', type='positive') dialog.close() await self._load_pietanze() except Exception as e: ui.notify(f'Errore nell\'eliminazione: {str(e)}', type='negative') async def _load_pietanze(self): """Load pietanze from API""" try: # Call actual API with current filters response = await self.api_client.get_pietanze( skip=0, limit=1000, # Load all pietanze for now search=self.search_filter if self.search_filter else None, allergeni=self.allergen_filter if self.allergen_filter else None ) # Extract pietanze from response pietanze_list = response.get('items', []) if isinstance(response, dict) else response # Format data for table display self.pietanze_data = [] for pietanza in pietanze_list: formatted_pietanza = { 'id': pietanza['id'], 'nome': pietanza['nome'], 'descrizione': pietanza.get('descrizione', ''), 'allergeni': pietanza.get('allergeni', []), 'allergeni_display': ', '.join(pietanza.get('allergeni', [])) if pietanza.get('allergeni') else 'Nessuno', 'created_at': pietanza.get('created_at', '') } self.pietanze_data.append(formatted_pietanza) self._update_table() except Exception as e: ui.notify(f'Errore nel caricamento pietanze: {str(e)}', type='negative') # Keep existing data on error self._update_table() def _update_table(self): """Update table with filtered data""" filtered_data = self._filter_pietanze() self.pietanze_table.rows = filtered_data ui.update() def _filter_pietanze(self) -> List[Dict[str, Any]]: """Filter pietanze based on search and allergen filters""" filtered = self.pietanze_data # Apply search filter if self.search_filter: search_lower = self.search_filter.lower() filtered = [ p for p in filtered if search_lower in p['nome'].lower() or (p['descrizione'] and search_lower in p['descrizione'].lower()) ] # Apply allergen filter if self.allergen_filter: filtered = [ p for p in filtered if any(allergen in p['allergeni'] for allergen in self.allergen_filter) ] return filtered def _on_search_change(self): """Handle search filter change""" self._update_table() def _on_filter_change(self): """Handle allergen filter change""" self._update_table()