""" Dashboard Layout Components This module contains reusable layout components for the main dashboard interface. These components handle the overall structure and navigation of the dashboard. """ from dash import html, dcc from typing import List, Dict, Any, Optional from datetime import datetime def create_header(title: str = "Crypto Trading Bot Dashboard", subtitle: str = "Real-time monitoring and bot management") -> html.Div: """ Create the main dashboard header component. Args: title: Main title text subtitle: Subtitle text Returns: Dash HTML component for the header """ return html.Div([ html.H1(f"🚀 {title}", style={'margin': '0', 'color': '#2c3e50', 'font-size': '28px'}), html.P(subtitle, style={'margin': '5px 0 0 0', 'color': '#7f8c8d', 'font-size': '14px'}) ], style={ 'padding': '20px', 'background-color': '#ecf0f1', 'border-bottom': '2px solid #bdc3c7', 'box-shadow': '0 2px 4px rgba(0,0,0,0.1)' }) def create_navigation_tabs(active_tab: str = 'market-data') -> dcc.Tabs: """ Create the main navigation tabs component. Args: active_tab: Default active tab Returns: Dash Tabs component """ tab_style = { 'borderBottom': '1px solid #d6d6d6', 'padding': '6px', 'fontWeight': 'bold' } tab_selected_style = { 'borderTop': '1px solid #d6d6d6', 'borderBottom': '1px solid #d6d6d6', 'backgroundColor': '#119DFF', 'color': 'white', 'padding': '6px' } return dcc.Tabs( id="main-tabs", value=active_tab, children=[ dcc.Tab( label='📊 Market Data', value='market-data', style=tab_style, selected_style=tab_selected_style ), dcc.Tab( label='🤖 Bot Management', value='bot-management', style=tab_style, selected_style=tab_selected_style ), dcc.Tab( label='📈 Performance', value='performance', style=tab_style, selected_style=tab_selected_style ), dcc.Tab( label='⚙️ System Health', value='system-health', style=tab_style, selected_style=tab_selected_style ), ], style={'margin': '10px 20px'} ) def create_content_container(content_id: str = 'tab-content') -> html.Div: """ Create the main content container. Args: content_id: HTML element ID for the content area Returns: Dash HTML component for content container """ return html.Div( id=content_id, style={ 'padding': '20px', 'min-height': '600px', 'background-color': '#ffffff' } ) def create_status_indicator(status: str, message: str, timestamp: Optional[datetime] = None) -> html.Div: """ Create a status indicator component. Args: status: Status type ('connected', 'error', 'warning', 'info') message: Status message timestamp: Optional timestamp for the status Returns: Dash HTML component for status indicator """ status_colors = { 'connected': '#27ae60', 'error': '#e74c3c', 'warning': '#f39c12', 'info': '#3498db' } status_icons = { 'connected': '🟢', 'error': '🔴', 'warning': '🟡', 'info': '🔵' } color = status_colors.get(status, '#7f8c8d') icon = status_icons.get(status, '⚪') components = [ html.Span(f"{icon} {message}", style={'color': color, 'font-weight': 'bold'}) ] if timestamp: components.append( html.P(f"Last updated: {timestamp.strftime('%H:%M:%S')}", style={'margin': '5px 0', 'color': '#7f8c8d', 'font-size': '12px'}) ) return html.Div(components) def create_card(title: str, content: Any, card_id: Optional[str] = None) -> html.Div: """ Create a card component for organizing content. Args: title: Card title content: Card content (can be any Dash component) card_id: Optional HTML element ID Returns: Dash HTML component for the card """ return html.Div([ html.H3(title, style={ 'margin': '0 0 15px 0', 'color': '#2c3e50', 'border-bottom': '2px solid #ecf0f1', 'padding-bottom': '10px' }), content ], style={ 'border': '1px solid #ddd', 'border-radius': '8px', 'padding': '20px', 'margin': '10px 0', 'background-color': '#ffffff', 'box-shadow': '0 2px 4px rgba(0,0,0,0.1)' }, id=card_id) def create_metric_display(metrics: Dict[str, str]) -> html.Div: """ Create a metrics display component. Args: metrics: Dictionary of metric names and values Returns: Dash HTML component for metrics display """ metric_components = [] for key, value in metrics.items(): # Color coding for percentage changes color = '#27ae60' if '+' in str(value) else '#e74c3c' if '-' in str(value) else '#2c3e50' metric_components.append( html.Div([ html.Strong(f"{key}: ", style={'color': '#2c3e50'}), html.Span(str(value), style={'color': color}) ], style={ 'margin': '8px 0', 'padding': '5px', 'background-color': '#f8f9fa', 'border-radius': '4px' }) ) return html.Div(metric_components, style={ 'display': 'grid', 'grid-template-columns': 'repeat(auto-fit, minmax(200px, 1fr))', 'gap': '10px' }) def create_selector_group(selectors: List[Dict[str, Any]]) -> html.Div: """ Create a group of selector components (dropdowns, etc.). Args: selectors: List of selector configurations Returns: Dash HTML component for selector group """ selector_components = [] for selector in selectors: selector_div = html.Div([ html.Label( selector.get('label', ''), style={'font-weight': 'bold', 'margin-bottom': '5px', 'display': 'block'} ), dcc.Dropdown( id=selector.get('id'), options=selector.get('options', []), value=selector.get('value'), style={'margin-bottom': '15px'} ) ], style={'width': '250px', 'margin': '10px 20px 10px 0', 'display': 'inline-block'}) selector_components.append(selector_div) return html.Div(selector_components, style={'margin': '20px 0'}) def create_loading_component(component_id: str, message: str = "Loading...") -> html.Div: """ Create a loading component for async operations. Args: component_id: ID for the component that will replace this loading screen message: Loading message Returns: Dash HTML component for loading screen """ return html.Div([ html.Div([ html.Div(className="loading-spinner", style={ 'border': '4px solid #f3f3f3', 'border-top': '4px solid #3498db', 'border-radius': '50%', 'width': '40px', 'height': '40px', 'animation': 'spin 2s linear infinite', 'margin': '0 auto 20px auto' }), html.P(message, style={'text-align': 'center', 'color': '#7f8c8d'}) ], style={ 'display': 'flex', 'flex-direction': 'column', 'align-items': 'center', 'justify-content': 'center', 'height': '200px' }) ], id=component_id) def create_placeholder_content(title: str, description: str, phase: str = "future implementation") -> html.Div: """ Create placeholder content for features not yet implemented. Args: title: Section title description: Description of what will be implemented phase: Implementation phase information Returns: Dash HTML component for placeholder content """ return html.Div([ html.H2(title, style={'color': '#2c3e50'}), html.Div([ html.P(description, style={'color': '#7f8c8d', 'font-size': '16px'}), html.P(f"🚧 Planned for {phase}", style={'color': '#f39c12', 'font-weight': 'bold', 'font-style': 'italic'}) ], style={ 'background-color': '#f8f9fa', 'padding': '20px', 'border-radius': '8px', 'border-left': '4px solid #f39c12' }) ]) # CSS Styles for animation (to be included in assets or inline styles) LOADING_CSS = """ @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } """