Patient Portal Redesign

Patient Portal Redesign

Branch/files: bista_menmd_website/data/patient_dashboard.xml (template), bista_menmd_website/controllers/login_redirect.py (patient_dashboard method)

Overview

Rebuilt the /patient-dashboard from the original single-hero-section layout to match the Doctors Dashboard's structural patterns and the design mockups created for this project. The page is now organized into distinct sections rather than one hero block, with a mobile-first approach

Page Structure (top to bottom)

  1. *NEW* Header - Now features a Welcome message with patient name, "Manage Prescriptions" and "Manage Account Preferences" buttons.
  2. *NEW * Order Status - Visual progress tracker (Order Placed → Processing → Shipped → Delivered) for the patient's most recent order, with a simplified fallback for orders that haven't had a status update in 7+ days, and a distinct mobile layout.
  3. *Updated* Your Prescriptions - Card carousel showing product name, provider, quantity remaining, and next fill date, with a green "AF" badge for AutoFill-enrolled prescriptions.
  4. *NEW* Account Information - Three cards: Important Information (Prescriptions/AutoFill/Appointments quick actions), Help & Support (Care Team, Book Clinical Call, Customer Support Line), and Account & Billing Summary (Shipping Address, Payment Method, Provider).
  5. *Updated* Current Promotions - Updated Promotional Slider.
  6. *Updated* Recommended Products - A redesigned carousel of cross-sell products, with a newworking ADD-to-cart button. These products are now linked directly to the Upsell and Cross-sell Optional Products field.
  7. *NEW* Resources - Educational Resources (Articles/Guides/Webinars tabs)
  8. *NEW* Frequently Asked Questions - Featuring 4 Questions that were provided by the Customer Support Team.

Order Status - Key Logic

  • Order lookup: matches orders where the patient is the direct partner_id, or where any order line's linked prescription belongs to the patient (order_line.z_rx_prescription_id.z_patient_id) — covers practice-pay/staff-placed orders billed under a different partner.
  • Staleness check: an order is "stale" if none of its z_si_status_* timestamps have changed in 7+ days. Stale orders show a simplified status message instead of the full tracker.
  • Tracker fill: "Order Placed" is always shown complete once an order exists (not gated on a pharmacy-receipt timestamp. The other three steps map to z_si_status_in_pharmacy_timestamp, z_si_status_shipped_timestamp, and z_si_status_delivered_timestamp.
  • Est. Ship Date: shows z_actual_ship_date under the Shipped step, but only before the order has actually shipped, disappears once z_si_status_shipped_timestamp is set.
  • Tracking URL: pulled from stock.picking.tracking_url (populated automatically once a shipping label is generated for the order) rather than a hand-built carrier URL. The TRACK PACKAGE button only renders when this field is populated.
  • Mobile: shows current stage headline + Track Package/View Orders buttons only, no tracker graphic, no line items.

Recommended Products - Key Logic

  • Primary source: cross-sell products (optional_product_ids, configured per-product on the Sales tab) tied to everything the patient has ever been prescribed, deduplicated against products they're already on.
  • Fallback: trending products (z_is_trending), same source/mechanism the original dashboard's "Trending in the Shop" section used — for patients with no Rx history.
  • Capped at 12 (RECOMMENDED_PRODUCTS_LIMIT), not vetted against a specific business requirement,  arbitrary pick, flagged for review.
  • ADD button: calls /shop/cart/update_json directly (the same route your own website_sale.py extends with the duplicate-OTC-in-cart guard), rather than reusing Odoo's core add-to-cart widget, which is jQuery-selector-scoped to the /shop grid and doesn't fire outside that container.
  • Cart feedback: custom toast notification (top-right, auto-dismiss), visually mimics but is not the literal core Odoo cart-notification component.
  • Carousel: desktop shows a static 4-up grid at ≤4 products, switches to a paged carousel with prev/next arrows above that. Mobile is always swipeable via CSS scroll-snap, with dot indicators tracking position.

Account & Billing Summary - Data Sources

  • Shipping Address: most recently added delivery-type child contact, falling back to the patient's own record.
  • Payment Method: most recently added, non-expired payment.token.
  • Provider: physician on the patient's most recent/active prescription (prescriptions[:1].z_physician), reuses the same tiered query (refillable-first, falling back to not-yet-expired) that drives the Prescriptions section, so "current provider" stays consistent with whichever Rx the rest of the page treats as current.

Live Chat Integration

"Connect With Team" triggers the real Live Chat bubble (im_livechat's LivechatButton component) rather than reimplementing chat-opening logic. The widget renders inside a Shadow DOM (.o-livechat-root), so the button reaches through host.shadowRoot.querySelector(...) to find it. Falls back to the existing /my/account link untouched if Live Chat isn't configured for this page or isn't currently available.

FAQ Content (Updated)

Replaced the original general company-overview placeholders with functional patient-portal FAQs per team feedback:

  1. Has My Prescription Been Received?  Check status under the Prescriptions tab.
  2. Where Is My Order? Tracking number is in the Orders section; track with the courier.
  3. Why Hasn't My Order Shipped Yet?  Orders process in received order, per shipping method timeframe.
  4. AutoFill vs. On-Demand Pricing  Compare via the info icon on AutoFill plans.