## ----include = FALSE---------------------------------------------------------- knitr::opts_chunk$set( collapse = TRUE, comment = "#>", eval = FALSE ) ## ----setup-------------------------------------------------------------------- # library(bidux) # library(shiny) # library(bslib) # library(dplyr) ## ----everything-dashboard-before---------------------------------------------- # # The "show everything" approach # ui_before <- navbarPage( # "User Engagement Analytics", # # tabPanel( # "Overview", # fluidRow( # # 12 KPIs across the top # column(2, valueBoxOutput("dau")), # column(2, valueBoxOutput("wau")), # column(2, valueBoxOutput("mau")), # column(2, valueBoxOutput("retention")), # column(2, valueBoxOutput("churn")), # column(2, valueBoxOutput("ltv")) # ), # fluidRow( # column(2, valueBoxOutput("sessions")), # column(2, valueBoxOutput("session_duration")), # column(2, valueBoxOutput("pages_per_session")), # column(2, valueBoxOutput("bounce_rate")), # column(2, valueBoxOutput("conversion")), # column(2, valueBoxOutput("revenue")) # ), # # # Multiple complex charts # fluidRow( # column(6, plotOutput("engagement_trend", height = "400px")), # column(6, plotOutput("cohort_analysis", height = "400px")) # ), # fluidRow( # column(4, plotOutput("funnel_chart")), # column(4, plotOutput("retention_curve")), # column(4, plotOutput("ltv_distribution")) # ) # ), # # tabPanel("Segments", "More detailed segmentation..."), # tabPanel("Cohorts", "Cohort analysis details..."), # tabPanel("Funnels", "Conversion funnel details..."), # tabPanel("Revenue", "Revenue analytics..."), # tabPanel("Product", "Product usage analytics...") # ) ## ----bid-everything-solution-------------------------------------------------- # # Stage 1: Interpret - Understand the real user need # interpret_result <- bid_interpret( # central_question = "How is our user engagement trending, and what needs attention?", # data_story = list( # hook = "User engagement metrics are spread across multiple systems", # context = "Leadership needs quick insights for weekly business reviews", # tension = "Current dashboards take too long to interpret", # resolution = "Provide immediate key insights with drill-down capability" # ), # user_personas = list( # list( # name = "Sarah (Product Manager)", # goals = "Quickly spot concerning trends and dive deeper when needed", # pain_points = "Too many metrics to process in limited meeting time", # technical_level = "Intermediate" # ), # list( # name = "Mike (Executive)", # goals = "Understand overall health at a glance", # pain_points = "Gets lost in details when just needs the big picture", # technical_level = "Basic" # ) # ) # ) # # # Stage 2: Notice - Identify the specific problem # notice_result <- bid_notice( # previous_stage = interpret_result, # problem = "Users experience information overload with 12+ simultaneous metrics", # evidence = "User interviews show 80% struggle to prioritize information, average time-to-insight is 5+ minutes" # ) # # # Stage 3: Anticipate - Consider cognitive biases # anticipate_result <- bid_anticipate( # previous_stage = notice_result, # bias_mitigations = list( # attention_bias = "Use size and color to direct focus to most important metrics first", # choice_overload = "Implement progressive disclosure - show key metrics, hide advanced analytics until requested", # anchoring = "Lead with the most important business metric to set proper context" # ) # ) # # # Stage 4: Structure - Organize for cognitive efficiency # structure_result <- bid_structure(previous_stage = anticipate_result) # # # Stage 5: Validate - Ensure actionable insights # validate_result <- bid_validate( # previous_stage = structure_result, # summary_panel = "Executive summary highlighting key trends and required actions", # collaboration = "Enable commenting and sharing of specific insights", # next_steps = c( # "Focus on the primary engagement metric trend", # "Investigate any red-flag indicators", # "Use drill-down for detailed analysis only when needed" # ) # ) ## ----everything-dashboard-after----------------------------------------------- # # The BID-informed approach: Progressive disclosure with clear hierarchy # ui_after <- page_fillable( # theme = bs_theme(version = 5), # # # Primary insight first (addresses anchoring bias) # layout_columns( # col_widths = c(8, 4), # # # Key insight panel # card( # card_header( # "📈 Engagement Health Score", # class = "bg-primary text-white" # ), # layout_columns( # value_box( # title = "Overall Score", # value = "87/100", # showcase = bs_icon("speedometer2", size = "2em"), # theme = "success", # p( # "↑ 5 points vs. last month", # style = "font-size: 0.9em; color: #666;" # ) # ), # div( # h5("Key Drivers", style = "margin-bottom: 10px;"), # tags$ul( # tags$li("DAU trending up (+12%)"), # tags$li("Retention stable (73%)"), # tags$li("⚠️ Session duration declining (-8%)") # ) # ) # ) # ), # # # Action panel # card( # card_header("🎯 Focus Areas"), # div( # tags$div( # class = "alert alert-warning", # tags$strong("Attention needed:"), # br(), # "Session duration declining. Investigate user experience." # ), # actionButton( # "investigate_sessions", # "Investigate Session Trends", # class = "btn btn-warning btn-sm" # ) # ) # ) # ), # # # Secondary metrics (progressive disclosure) # card( # card_header( # div( # style = "display: flex; justify-content: space-between; align-items: center;", # span("📊 Detailed Metrics"), # actionButton( # "toggle_details", # "Show Details", # class = "btn btn-outline-secondary btn-sm" # ) # ) # ), # # # Hidden by default, shown on demand # conditionalPanel( # condition = "input.toggle_details % 2 == 1", # layout_columns( # col_widths = c(3, 3, 3, 3), # value_box("DAU", "45.2K", icon = "people"), # value_box("Retention", "73%", icon = "arrow-clockwise"), # value_box("Sessions", "2.1M", icon = "activity"), # value_box("Revenue", "$127K", icon = "currency-dollar") # ), # # # Charts appear only when details are requested # layout_columns( # col_widths = c(6, 6), # card( # card_header("Engagement Trend"), # plotOutput("engagement_trend_focused", height = "300px") # ), # card( # card_header("Key Drivers Analysis"), # plotOutput("drivers_analysis", height = "300px") # ) # ) # ) # ) # ) ## ----data-dump-before--------------------------------------------------------- # ui_sales_before <- fluidPage( # titlePanel("Q4 Sales Performance Dashboard"), # # # Massive filter section # sidebarLayout( # sidebarPanel( # dateRangeInput("date_range", "Date Range"), # selectInput("region", "Region", choices = regions, multiple = TRUE), # selectInput( # "product", # "Product Line", # choices = products, # multiple = TRUE # ), # selectInput("salesperson", "Sales Rep", choices = reps, multiple = TRUE), # selectInput( # "customer_segment", # "Customer Segment", # choices = segments, # multiple = TRUE # ), # selectInput( # "deal_size", # "Deal Size", # choices = deal_sizes, # multiple = TRUE # ), # checkboxGroupInput("deal_stage", "Deal Stages", choices = stages), # numericInput("min_value", "Minimum Deal Value", value = 0), # numericInput("max_value", "Maximum Deal Value", value = 1000000), # radioButtons("currency", "Currency", choices = c("USD", "EUR", "GBP")), # actionButton("apply_filters", "Apply Filters", class = "btn-primary") # ), # # mainPanel( # tabsetPanel( # tabPanel( # "Summary", # fluidRow( # column(3, valueBoxOutput("total_revenue")), # column(3, valueBoxOutput("deal_count")), # column(3, valueBoxOutput("avg_deal_size")), # column(3, valueBoxOutput("win_rate")) # ), # plotOutput("revenue_chart", height = "600px") # ), # tabPanel("By Region", dataTableOutput("region_table")), # tabPanel("By Product", dataTableOutput("product_table")), # tabPanel("By Rep", dataTableOutput("rep_table")), # tabPanel("Pipeline", dataTableOutput("pipeline_table")), # tabPanel("Forecasting", plotOutput("forecast_chart")) # ) # ) # ) # ) ## ----sales-bid-solution------------------------------------------------------- # # Apply BID framework focusing on sales manager workflow # sales_interpret <- bid_interpret( # central_question = "What deals need my attention this week?", # data_story = list( # hook = "Sales managers spend 2+ hours weekly creating status reports", # context = "They need to quickly identify at-risk deals and top opportunities", # tension = "Current data requires extensive filtering and analysis", # resolution = "Provide intelligent prioritization with drill-down capability" # ), # user_personas = list( # list( # name = "Jennifer (Regional Sales Manager)", # goals = "Identify at-risk deals, spot top opportunities, prepare for team meetings", # pain_points = "Too much filtering required to find actionable insights", # technical_level = "Intermediate" # ) # ) # ) # # sales_notice <- bid_notice( # previous_stage = sales_interpret, # problem = "Sales managers overwhelmed by filter complexity and data volume", # evidence = "Users spend average 15 minutes per session just setting up filters, 40% abandon before getting insights" # ) # # sales_anticipate <- bid_anticipate( # previous_stage = sales_notice, # bias_mitigations = list( # recency_bias = "Show deals by urgency, not just recent activity", # confirmation_bias = "Highlight both positive and concerning trends", # choice_overload = "Limit initial choices to most common use cases" # ) # ) # # sales_structure <- bid_structure(previous_stage = sales_anticipate) ## ----sales-dashboard-after---------------------------------------------------- # ui_sales_after <- page_navbar( # title = "Sales Command Center", # theme = bs_theme(version = 5, preset = "bootstrap"), # # nav_panel( # "🚨 Needs Attention", # layout_columns( # # Immediate action items # card( # card_header( # "🔥 Urgent - Deals at Risk", # class = "bg-danger text-white" # ), # card_body( # p("3 deals worth $340K need immediate attention"), # layout_columns( # col_widths = c(6, 6), # div( # h6("MegaCorp Deal - $180K"), # p( # "❌ No activity in 14 days", # style = "color: #dc3545; margin: 0;" # ), # p("Owner: Mike Chen", style = "font-size: 0.9em; color: #666;") # ), # div( # actionButton( # "view_megacorp", # "View Details", # class = "btn btn-sm btn-outline-danger" # ), # actionButton( # "contact_mike", # "Contact Mike", # class = "btn btn-sm btn-danger" # ) # ) # ) # ) # ), # # # Opportunities # card( # card_header("⭐ Hot Opportunities", class = "bg-success text-white"), # card_body( # p("2 deals worth $280K ready to close"), # actionButton( # "view_opportunities", # "Review Opportunities", # class = "btn btn-success btn-sm" # ) # ) # ) # ), # # # Smart filters (only show when needed) # conditionalPanel( # condition = "input.show_filters", # card( # card_header("🔍 Refine Focus"), # layout_columns( # col_widths = c(3, 3, 3, 3), # selectInput("quick_region", "Region", choices = c("All", regions)), # selectInput( # "quick_timeframe", # "Timeframe", # choices = c("This Week", "This Month", "This Quarter") # ), # selectInput( # "quick_value", # "Deal Size", # choices = c("All", ">$50K", ">$100K", ">$250K") # ), # actionButton( # "show_all_filters", # "More Filters...", # class = "btn btn-outline-secondary btn-sm" # ) # ) # ) # ) # ), # # nav_panel( # "📊 Performance", # layout_columns( # col_widths = c(4, 4, 4), # value_box( # "This Month", # "$1.2M", # "vs. $980K target (+22%)", # showcase = bs_icon("graph-up"), # theme = "success" # ), # value_box( # "Pipeline Health", # "Strong", # "3.2x coverage ratio", # showcase = bs_icon("speedometer2"), # theme = "info" # ), # value_box( # "Team Status", # "On Track", # "8 of 10 reps hitting quota", # showcase = bs_icon("people"), # theme = "success" # ) # ), # # card( # card_header("📈 Key Trends"), # plotOutput("performance_trends", height = "400px") # ) # ), # # nav_panel( # "🎯 Team Focus", # # Team-specific insights # p("Individual rep performance and coaching opportunities...") # ) # ) ## ----technical-metrics-solution----------------------------------------------- # # Interpret stage: Understand different user needs # technical_interpret <- bid_interpret( # central_question = "How is our application performing and what needs attention?", # user_personas = list( # list( # name = "DevOps Engineer", # goals = "Identify performance bottlenecks and system issues", # pain_points = "Needs detailed metrics and historical trends", # technical_level = "Expert" # ), # list( # name = "Engineering Manager", # goals = "Understand overall system health and team priorities", # pain_points = "Needs summary view but ability to drill down", # technical_level = "Advanced" # ), # list( # name = "Executive", # goals = "Understand business impact of technical issues", # pain_points = "Technical details are overwhelming", # technical_level = "Basic" # ) # ) # ) ## ----technical-dashboard-after------------------------------------------------ # # Adaptive interface based on user role # ui_technical_after <- page_sidebar( # sidebar = sidebar( # # Role selector affects entire interface # radioButtons( # "user_role", # "View Mode:", # choices = c( # "Executive Summary" = "executive", # "Management View" = "manager", # "Technical Details" = "engineer" # ), # selected = "executive" # ) # ), # # # Executive view: Business impact focus # conditionalPanel( # condition = "input.user_role == 'executive'", # h2("🟢 System Health: Good"), # # layout_columns( # col_widths = c(6, 6), # card( # card_header("Business Impact"), # value_box( # "Service Availability", # "99.8%", # "Within SLA targets", # theme = "success" # ), # value_box( # "User Experience", # "Good", # "Page loads < 2 seconds", # theme = "success" # ) # ), # card( # card_header("Action Items"), # div( # class = "alert alert-info", # "✅ No critical issues requiring immediate attention" # ), # p("Next scheduled maintenance: Friday 2am") # ) # ) # ), # # # Manager view: Balance of summary and detail # conditionalPanel( # condition = "input.user_role == 'manager'", # layout_columns( # col_widths = c(3, 3, 3, 3), # value_box("Uptime", "99.8%", theme = "success"), # value_box("Response Time", "1.2s", theme = "success"), # value_box("Error Rate", "0.02%", theme = "success"), # value_box("Throughput", "15K/min", theme = "info") # ), # # card( # card_header("System Trends"), # plotOutput("system_trends", height = "300px") # ), # # card( # card_header("Team Alerts"), # p("2 minor alerts resolved this week"), # actionButton("view_alerts", "View Alert History") # ) # ), # # # Engineer view: Full technical detail # conditionalPanel( # condition = "input.user_role == 'engineer'", # # Comprehensive technical metrics # tabsetPanel( # tabPanel("Performance", "Detailed performance metrics..."), # tabPanel("Infrastructure", "Server and database metrics..."), # tabPanel("Alerts", "Full alert history and configuration..."), # tabPanel("Logs", "System logs and debugging info...") # ) # ) # ) ## ----user-intent-focus-------------------------------------------------------- # # ❌ Data-structure driven # ui_wrong <- tabPanel( # "Database Tables", # tabPanel("Users Table", dataTableOutput("users")), # tabPanel("Orders Table", dataTableOutput("orders")), # tabPanel("Products Table", dataTableOutput("products")) # ) # # # ✅ User-intent driven # ui_right <- tabPanel( # "Customer Insights", # card_body( # h4("What customers need your attention?"), # # Show actionable customer insights # ) # ) ## ----progressive-disclosure--------------------------------------------------- # # ❌ Everything visible at once # ui_dense <- fluidRow( # column(2, metric1), # column(2, metric2), # column(2, metric3), # column(2, metric4), # column(2, metric5), # column(2, metric6) # ) # # # ✅ Key information first, details on demand # ui_progressive <- div( # value_box("Key Metric", "Primary value"), # actionButton("show_details", "View Supporting Metrics"), # conditionalPanel( # condition = "input.show_details", # # Additional metrics here # ) # ) ## ----context-over-numbers----------------------------------------------------- # # ❌ Raw number without meaning # valueBox("Revenue", "$127,432") # # # ✅ Number with context and meaning # value_box( # "Revenue Progress", # "$127K", # "22% above $104K target", # showcase = bs_icon("graph-up"), # theme = "success" # )