[Sales Rep Interactive App](web_app:GeudQIv)

A Dash webapp providing an interactive HCP-level planning view with advanced filtering, a sortable action table, and a drill-down detail panel for each HCP. Designed for reps and marketing ops who need more granular control than the native dashboard provides - including the ability to filter across multiple dimensions simultaneously and review the full AI-generated justification for any recommendation in one click. For guidance on building and deploying Dash webapps in Dataiku, refer to the [Dataiku Dash Developer Guide](https://developer.dataiku.com/latest/tutorials/webapps/dash/basics/index.html#gsc.tab=0).


### Prerequisites
Before running this webapp, ensure the code environment includes the following packages in addition to the standard Dataiku requirements (see [Technical Requirements](article:22) article).
> dash
>dash-bootstrap-components
>flask

### Source Dataset
The webapp reads from [nba_recommendation_features_final_by_hcp_id_generated] (dataset:nba_recommendation_features_final_by_hcp_id_generated). Only the required columns are loaded at startup for performance. The dataset is sorted by `expected_impact` descending on load - the optimizer metric is used for ranking while `expected_lift_pct` is displayed to the user.

### Layout
The webapp uses a two-panel layout:

**Left panel - Filters (25% width)** Seven filter controls that update the action table and KPI tiles in real time:
- Territory
- Segment
- Specialty
- Recommended Channel
- Priority (Priority / Strong Candidate / Moderate Opportunity / Moderate)
- Engagement Tier (high / medium / low)
- Rx Trend (increasing / stable / decreasing)
- Days Since Last Engagement (range slider)

A Reset Filters button restores all controls to their default state. A Refresh button reloads the full webapp.
**Right panel - Recommendations (75% width)**
- Four KPI tiles: Total Actions · Priority & Strong Candidate Actions · Total Rx Volume · Total Actions Cost
- Sortable and filterable action table with columns: HCP Name · Specialty · Segment · Territory · Channel · Priority · Engagement Tier · Impact Tier · Exp. Lift (%) · p(engage) · CPA ($)
- HCP detail panel — appears when a row is selected


### HCP Detail Panel
Clicking any row in the table opens a detail panel showing three sections side by side and the full AI justification below.

- **Recommendation** Channel · Engagement Tier · Impact Tier · p(engage) · Expected Lift (% above avg weekly Rx) · CPA
- **Engagement History** Overall success rate · Last contact (days ago and channel) · Channel success rate (12w) · Days since last channel attempt and last channel success · Per-channel success counts (Rep / Phone / Webinar / Email / Digital) · Engagement journey sequence
- **Prescribing Activity** Rx trend · Last week Rx · Last 4 weeks Rx · Avg weekly Rx · Total Rx (all time)
- **AI-Generated Recommendation Justification** Three sections parsed from `llm_output`:
  - HCP Engagement Profile - commercial standing and engagement summary
  - Key Drivers - SHAP-grounded justification bullets with strength labels
  - Rep Guidance - CRM-ready narrative for call preparation

### Priority Colour Coding
Priority labels are rendered as colour-coded badges throughout the table and detail panel:

| Label | Colour |
|---|---|
| Priority | Red `#d32f2f` |
| Strong Candidate | Orange `#f57c00` |
| Moderate Opportunity | Blue `#1976d2` |
| Moderate | Grey `#616161` |

Engagement and impact tier badges follow the same logic: high = green, medium = amber, low = grey.

### Key Implementation Notes
- All filter callbacks feed into a `dcc.Store` component (`filtered_store`) that holds the filtered dataset as a dict. The table, KPI tiles, and detail panel all read from this store — a single filter change triggers one data computation and all downstream components update from the cached result.
- The detail panel callback reads directly from the full unfiltered dataframe using `hcp_id` as a key — ensuring the detail view always shows complete data regardless of the active filters.
- `safe_int` and `safe_float` helpers handle null values throughout the detail panel to prevent rendering errors on HCPs with incomplete history.
- The LLM output parser handles both `## SECTION:` prefixed and plain`SECTION:` markers for robustness across different LLM output formats.