import streamlit as st import pandas as pd import plotly.express as px from pathlib import Path st.set_page_config( page_title="Food Delivery Analytics", page_icon="🍔", layout="wide" ) def find_file(filename: str) -> Path: candidates = [ Path("/app") / filename, Path("/app/src") / filename, Path(__file__).resolve().parent / filename, Path(__file__).resolve().parent.parent / filename, ] for path in candidates: if path.exists(): return path raise FileNotFoundError( f"Could not find {filename}. Checked: " + ", ".join(str(p) for p in candidates) ) @st.cache_data def load_data(): real_df = pd.read_csv(find_file("real_world_driver_data.csv")) metrics_df = pd.read_csv(find_file("synthetic_delivery_metrics.csv")) reviews_df = pd.read_csv(find_file("synthetic_customer_reviews.csv")) features_df = pd.read_csv(find_file("synthetic_driver_features.csv")) monthly_df = pd.read_csv(find_file("synthetic_monthly_delivery_series.csv")) return real_df, metrics_df, reviews_df, features_df, monthly_df real_df, metrics_df, reviews_df, features_df, monthly_df = load_data() monthly_df["month"] = pd.to_datetime(monthly_df["month"]) # KPIs total_drivers = features_df["driver_id"].nunique() total_deliveries = int(metrics_df["deliveries_completed"].sum()) avg_rating = round(features_df["Delivery_person_Ratings"].mean(), 2) total_reviews = int(reviews_df.shape[0]) # Sidebar st.sidebar.title("Filters") city_options = ["All"] + sorted(features_df["City"].dropna().unique().tolist()) vehicle_options = ["All"] + sorted(features_df["Type_of_vehicle"].dropna().unique().tolist()) selected_city = st.sidebar.selectbox("City", city_options) selected_vehicle = st.sidebar.selectbox("Vehicle Type", vehicle_options) filtered_features = features_df.copy() if selected_city != "All": filtered_features = filtered_features[filtered_features["City"] == selected_city] if selected_vehicle != "All": filtered_features = filtered_features[filtered_features["Type_of_vehicle"] == selected_vehicle] filtered_driver_ids = filtered_features["driver_id"].unique() filtered_metrics = metrics_df[metrics_df["driver_id"].isin(filtered_driver_ids)].copy() filtered_reviews = reviews_df[reviews_df["driver_id"].isin(filtered_driver_ids)].copy() filtered_total_drivers = filtered_features["driver_id"].nunique() filtered_total_deliveries = int(filtered_metrics["deliveries_completed"].sum()) if not filtered_metrics.empty else 0 filtered_avg_rating = round(filtered_features["Delivery_person_Ratings"].mean(), 2) if not filtered_features.empty else 0 filtered_total_reviews = int(filtered_reviews.shape[0]) # Header st.markdown("""

🍔 Food Delivery Analytics Dashboard

Analyze driver performance, customer sentiment, and delivery trends

""", unsafe_allow_html=True) st.markdown("---") # KPI cards col1, col2, col3, col4 = st.columns(4) col1.metric("🚚 Drivers", filtered_total_drivers) col2.metric("📦 Deliveries", f"{filtered_total_deliveries:,}") col3.metric("⭐ Avg Rating", filtered_avg_rating) col4.metric("💬 Reviews", f"{filtered_total_reviews:,}") st.markdown("---") tab1, tab2, tab3, tab4 = st.tabs([ "Overview", "Driver Performance", "Customer Reviews", "Monthly Trends" ]) with tab1: st.subheader("Dataset Overview") st.write("This dashboard combines driver performance, delivery activity, and customer sentiment data.") col_a, col_b = st.columns(2) with col_a: if not filtered_features.empty: fig_overview_1 = px.histogram( filtered_features, x="performance_tier", title="Performance Tier Distribution" ) st.plotly_chart(fig_overview_1, use_container_width=True) with col_b: if not filtered_features.empty: city_counts = filtered_features["City"].value_counts().reset_index() city_counts.columns = ["City", "count"] fig_overview_2 = px.bar( city_counts, x="City", y="count", title="Drivers by City" ) st.plotly_chart(fig_overview_2, use_container_width=True) st.markdown("### Data Preview") st.dataframe(filtered_features.head(10), use_container_width=True) with tab2: st.subheader("Driver Performance") if not filtered_features.empty: top_drivers = filtered_features.sort_values("total_deliveries", ascending=False).head(10) fig1 = px.bar( top_drivers, x="driver_id", y="total_deliveries", color="performance_tier", title="Top 10 Drivers by Total Deliveries" ) st.plotly_chart(fig1, use_container_width=True) fig2 = px.scatter( filtered_features, x="avg_delivery_time", y="Delivery_person_Ratings", color="sentiment_label", hover_name="driver_id", title="Average Delivery Time vs Driver Rating" ) st.plotly_chart(fig2, use_container_width=True) else: st.warning("No driver data available for the selected filters.") with tab3: st.subheader("Customer Reviews") if not filtered_reviews.empty: col_a, col_b = st.columns(2) with col_a: sentiment_counts = filtered_reviews["sentiment_label"].value_counts().reset_index() sentiment_counts.columns = ["sentiment_label", "count"] fig3 = px.pie( sentiment_counts, names="sentiment_label", values="count", title="Customer Review Sentiment Distribution" ) st.plotly_chart(fig3, use_container_width=True) with col_b: avg_rating_by_sentiment = ( filtered_reviews.groupby("sentiment_label", as_index=False)["driver_rating"] .mean() ) fig4 = px.bar( avg_rating_by_sentiment, x="sentiment_label", y="driver_rating", title="Average Rating by Sentiment" ) st.plotly_chart(fig4, use_container_width=True) st.write("Sample reviews:") st.dataframe( filtered_reviews[["driver_id", "sentiment_label", "driver_rating", "review_text"]].head(15), use_container_width=True ) else: st.warning("No review data available for the selected filters.") with tab4: st.subheader("Monthly Delivery Trends") if not filtered_metrics.empty: monthly_trend = ( filtered_metrics.groupby("month", as_index=False)["deliveries_completed"] .sum() .rename(columns={"deliveries_completed": "total_deliveries"}) ) monthly_trend["month"] = pd.to_datetime(monthly_trend["month"]) fig4 = px.line( monthly_trend, x="month", y="total_deliveries", markers=True, title="Total Deliveries Over Time" ) st.plotly_chart(fig4, use_container_width=True) else: st.warning("No monthly delivery data available for the selected filters.") import requests st.markdown("---") st.subheader("🤖 AI Insight") webhook_url = "https://jq7hhh.app.n8n.cloud/webhook/3dc59db1-0e3d-4b73-bdc1-bbe5168feb6f" if st.button("Generate AI Insight", key="n8n_ai_insight_button"): payload = { "city": selected_city, "vehicle_type": selected_vehicle, "drivers": int(filtered_total_drivers), "deliveries": int(filtered_total_deliveries), "avg_rating": float(filtered_avg_rating), "reviews": int(filtered_total_reviews) } try: response = requests.post(webhook_url, json=payload, timeout=20) if response.status_code == 200: result = response.json() st.success(result.get("Insight", "Insight generated successfully.")) else: st.error(f"Webhook error: {response.status_code}") st.write(response.text) except Exception as e: st.error(f"Request failed: {e}")