Spaces:
Running
Running
| # ui/renderers.py | |
| from datetime import datetime | |
| from config import AGENTS_INFO | |
| def _format_iso_time(iso_str: str) -> str: | |
| if not iso_str or iso_str == "N/A": return "" | |
| try: | |
| dt = datetime.fromisoformat(iso_str) | |
| return dt.strftime("%H:%M") | |
| except Exception: | |
| if "T" in iso_str: return iso_str.split("T")[1][:5] | |
| return iso_str | |
| def create_agent_stream_output(text: str = None) -> str: | |
| return f'<div style="font-family: monospace; color: #334155;">{text}</div>' | |
| def create_agent_dashboard(status_dict: dict) -> str: | |
| leader_key = 'team' | |
| member_keys = ['scout', 'weatherman', 'optimizer', 'navigator', 'presenter'] | |
| def _render_card(key): | |
| info = AGENTS_INFO.get(key, {}) | |
| state = status_dict.get(key, {}) | |
| status = state.get('status', 'idle') | |
| msg = state.get('message', 'Standby') | |
| active_class = "working" if status == "working" else "" | |
| icon = info.get('icon', 'π€') | |
| name = info.get('name', key.title()) | |
| role = info.get('role', 'Agent') | |
| color = info.get('color', '#6366f1') | |
| return f""" | |
| <div class="agent-card-wrap {active_class}"> | |
| <div class="agent-card-inner" style="border-top: 3px solid {color}"> | |
| <div class="agent-avatar">{icon}</div> | |
| <div class="agent-name">{name}</div> | |
| <div class="agent-role">{role}</div> | |
| <div class="status-badge">{msg}</div> | |
| </div> | |
| </div> | |
| """ | |
| html = f""" | |
| <div class="agent-war-room"> | |
| <div class="org-chart"> | |
| <div class="org-level"> | |
| {_render_card(leader_key)} | |
| </div> | |
| <div class="connector-line"></div> | |
| <div class="connector-horizontal"></div> | |
| <div class="org-level"> | |
| {''.join([_render_card(k) for k in member_keys])} | |
| </div> | |
| </div> | |
| </div> | |
| """ | |
| return html | |
| def create_summary_card(total_tasks: int, high_priority: int, total_time: int, location: str = "Taipei City", | |
| date: str = "Today") -> str: | |
| return f""" | |
| <div style="background: #f8fafc; border-radius: 12px; padding: 16px; margin-bottom: 20px; border: 1px solid #e2e8f0;"> | |
| <div style="display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 12px;"> | |
| <div> | |
| <div style="font-size: 0.8rem; color: #64748b; font-weight: 600;">TRIP SUMMARY</div> | |
| <div style="font-size: 1.1rem; font-weight: 700; color: #1e293b;">{location}</div> | |
| <div style="font-size: 0.9rem; color: #6366f1;">π {date}</div> | |
| </div> | |
| <div style="text-align: right;"> | |
| <div style="font-size: 2rem; font-weight: 800; color: #6366f1; line-height: 1;">{total_tasks}</div> | |
| <div style="font-size: 0.8rem; color: #64748b;">Tasks</div> | |
| </div> | |
| </div> | |
| <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 8px;"> | |
| <div style="background: white; padding: 8px; border-radius: 8px; text-align: center; border: 1px solid #e2e8f0;"> | |
| <div style="font-size: 0.8rem; color: #64748b;">Duration</div> | |
| <div style="font-weight: 600; color: #334155;">{total_time} min</div> | |
| </div> | |
| <div style="background: white; padding: 8px; border-radius: 8px; text-align: center; border: 1px solid #e2e8f0;"> | |
| <div style="font-size: 0.8rem; color: #64748b;">High Prio</div> | |
| <div style="font-weight: 600; color: #ef4444;">{high_priority}</div> | |
| </div> | |
| </div> | |
| </div> | |
| """ | |
| def create_task_card(task_num: int, task_title: str, priority: str, time_window: dict, duration: str, location: str, | |
| icon: str = "π") -> str: | |
| p_color = {"HIGH": "#ef4444", "MEDIUM": "#f59e0b", "LOW": "#10b981"}.get(priority.upper(), "#94a3b8") | |
| display_time = "Anytime" | |
| if isinstance(time_window, dict): | |
| s_clean = _format_iso_time(time_window.get('earliest_time', '')) | |
| e_clean = _format_iso_time(time_window.get('latest_time', '')) | |
| if s_clean and e_clean: | |
| display_time = f"{s_clean} - {e_clean}" | |
| elif s_clean: | |
| display_time = f"After {s_clean}" | |
| elif time_window: | |
| display_time = str(time_window) | |
| return f""" | |
| <div class="task-card-item" style="border-left: 4px solid {p_color};"> | |
| <div style="display: flex; justify-content: space-between; margin-bottom: 8px;"> | |
| <div style="font-weight: 700; color: #334155; display: flex; align-items: center; gap: 8px;"> | |
| <span style="background:#f1f5f9; padding:4px; border-radius:6px;">{icon}</span> | |
| {task_title} | |
| </div> | |
| <span style="font-size: 0.7rem; font-weight: 700; color: {p_color}; background: {p_color}15; padding: 2px 8px; border-radius: 12px; height: fit-content;">{priority}</span> | |
| </div> | |
| <div style="font-size: 0.85rem; color: #64748b; display: flex; flex-direction: column; gap: 4px;"> | |
| <div style="display: flex; align-items: center; gap: 6px;"><span>π</span> {location}</div> | |
| <div style="display: flex; align-items: center; gap: 6px;"><span>π</span> {display_time} <span style="color:#cbd5e1">|</span> β³ {duration}</div> | |
| </div> | |
| </div> | |
| """ | |
| # π₯π₯π₯ Updated Timeline Function | |
| def create_timeline_html_enhanced(timeline): | |
| if not timeline: | |
| return """ | |
| <div style="text-align: center; padding: 20px; color: #94a3b8;"> | |
| No timeline data available yet. | |
| </div> | |
| """ | |
| html = '<div class="timeline-container">' | |
| for i, stop in enumerate(timeline): | |
| location = stop.get('location', 'Unknown') | |
| time_str = stop.get('time', '') | |
| if not time_str or time_str == "N/A": time_str = "Flexible Time" | |
| weather_str = stop.get('weather', '') | |
| weather_html = "" | |
| if weather_str and weather_str != "N/A": | |
| weather_html = f'<div class="timeline-meta">π€οΈ {weather_str}</div>' | |
| html += f""" | |
| <div class="timeline-stop"> | |
| <div class="timeline-left"> | |
| <div class="timeline-marker"></div> | |
| </div> | |
| <div class="timeline-card"> | |
| <div class="timeline-header"> | |
| <div class="timeline-location">{location}</div> | |
| <div class="timeline-time-badge">π {time_str}</div> | |
| </div> | |
| {weather_html} | |
| </div> | |
| </div> | |
| """ | |
| html += '</div>' | |
| return html | |
| # Empty Placeholders | |
| def create_metrics_cards(metrics, traffic): return "" | |
| def create_result_visualization(tasks, data): return "" | |
| def generate_chat_history_html_bubble(session): return "" |