From 8430cd1e25a0af6bad72895f1778c06ad21fc755 Mon Sep 17 00:00:00 2001
From: Nick Diehl <47604184+ncdiehl11@users.noreply.github.com>
Date: Wed, 7 Aug 2024 17:21:31 -0400
Subject: [PATCH] fix(app, components): fix labware map view selection ODD
 (#15930)

Render proper modal depending on if labware is top element of stack or
loaded directly on deck. Refactors to use the same state variable to
keep track of the selected labware, and determines which modal to show
depending on if the selected labware was loaded onto a module/adapter or
directly onto the deck.
---
 .../SetupLabware/LabwareStackModal.tsx        | 31 ++++++++++++--
 .../SetupLabware/SetupLabwareMap.tsx          |  1 +
 .../organisms/ProtocolSetupLabware/index.tsx  | 41 +++++++------------
 .../Labware/LabwareStackRender.tsx            |  7 ++--
 4 files changed, 47 insertions(+), 33 deletions(-)

diff --git a/app/src/organisms/Devices/ProtocolRun/SetupLabware/LabwareStackModal.tsx b/app/src/organisms/Devices/ProtocolRun/SetupLabware/LabwareStackModal.tsx
index 83fdf1d9260..80bd38a3255 100644
--- a/app/src/organisms/Devices/ProtocolRun/SetupLabware/LabwareStackModal.tsx
+++ b/app/src/organisms/Devices/ProtocolRun/SetupLabware/LabwareStackModal.tsx
@@ -23,9 +23,17 @@ import { getLocationInfoNames } from '../utils/getLocationInfoNames'
 import { getSlotLabwareDefinition } from '../utils/getSlotLabwareDefinition'
 import { Divider } from '../../../../atoms/structure'
 import { getModuleImage } from '../SetupModuleAndDeck/utils'
-import { getModuleDisplayName } from '@opentrons/shared-data'
+import {
+  FLEX_ROBOT_TYPE,
+  getModuleDisplayName,
+  getModuleType,
+  TC_MODULE_LOCATION_OT2,
+  TC_MODULE_LOCATION_OT3,
+} from '@opentrons/shared-data'
 import tiprackAdapter from '../../../../assets/images/labware/opentrons_flex_96_tiprack_adapter.png'
 
+import type { RobotType } from '@opentrons/shared-data'
+
 const HIDE_SCROLLBAR = css`
   ::-webkit-scrollbar {
     display: none;
@@ -36,12 +44,13 @@ interface LabwareStackModalProps {
   labwareIdTop: string
   runId: string
   closeModal: () => void
+  robotType?: RobotType
 }
 
 export const LabwareStackModal = (
   props: LabwareStackModalProps
 ): JSX.Element | null => {
-  const { labwareIdTop, runId, closeModal } = props
+  const { labwareIdTop, runId, closeModal, robotType = FLEX_ROBOT_TYPE } = props
   const { t } = useTranslation('protocol_setup')
   const isOnDevice = useSelector(getIsOnDevice)
   const protocolData = useMostRecentCompletedAnalysis(runId)
@@ -60,6 +69,14 @@ export const LabwareStackModal = (
 
   const topDefinition = getSlotLabwareDefinition(labwareIdTop, commands)
   const adapterDef = getSlotLabwareDefinition(adapterId ?? '', commands)
+  const isModuleThermocycler =
+    moduleModel == null
+      ? false
+      : getModuleType(moduleModel) === 'thermocyclerModuleType'
+  const thermocyclerLocation =
+    robotType === FLEX_ROBOT_TYPE
+      ? TC_MODULE_LOCATION_OT3
+      : TC_MODULE_LOCATION_OT2
   const moduleDisplayName =
     moduleModel != null ? getModuleDisplayName(moduleModel) : null ?? ''
   const tiprackAdapterImg = (
@@ -80,7 +97,9 @@ export const LabwareStackModal = (
       header={{
         title: (
           <Flex gridGap={SPACING.spacing4}>
-            <DeckInfoLabel deckLabel={slotName} />
+            <DeckInfoLabel
+              deckLabel={isModuleThermocycler ? thermocyclerLocation : slotName}
+            />
             <DeckInfoLabel iconName="stacked" />
           </Flex>
         ),
@@ -156,7 +175,11 @@ export const LabwareStackModal = (
       onClose={closeModal}
       closeOnOutsideClick
       title={t('stacked_slot')}
-      titleElement1={<DeckInfoLabel deckLabel={slotName} />}
+      titleElement1={
+        <DeckInfoLabel
+          deckLabel={isModuleThermocycler ? thermocyclerLocation : slotName}
+        />
+      }
       titleElement2={<DeckInfoLabel iconName="stacked" />}
       childrenPadding={0}
       marginLeft="0"
diff --git a/app/src/organisms/Devices/ProtocolRun/SetupLabware/SetupLabwareMap.tsx b/app/src/organisms/Devices/ProtocolRun/SetupLabware/SetupLabwareMap.tsx
index 9a3c04fdc5f..8a35d8d203e 100644
--- a/app/src/organisms/Devices/ProtocolRun/SetupLabware/SetupLabwareMap.tsx
+++ b/app/src/organisms/Devices/ProtocolRun/SetupLabware/SetupLabwareMap.tsx
@@ -180,6 +180,7 @@ export function SetupLabwareMap({
           closeModal={() => {
             setLabwareStackDetailsLabwareId(null)
           }}
+          robotType={robotType}
         />
       )}
     </Flex>
diff --git a/app/src/organisms/ProtocolSetupLabware/index.tsx b/app/src/organisms/ProtocolSetupLabware/index.tsx
index 919d887f491..cbc8d363b4b 100644
--- a/app/src/organisms/ProtocolSetupLabware/index.tsx
+++ b/app/src/organisms/ProtocolSetupLabware/index.tsx
@@ -98,6 +98,7 @@ export function ProtocolSetupLabware({
     | (LabwareDefinition2 & {
         location: LabwareLocation
         nickName: string | null
+        id: string
       })
     | null
   >(null)
@@ -143,13 +144,21 @@ export function ProtocolSetupLabware({
         ...labwareDef,
         location: foundLabware.location,
         nickName: nickName ?? null,
+        id: labwareId,
       })
       setShowLabwareDetailsModal(true)
     }
   }
+  const selectedLabwareIsTopOfStack = mostRecentAnalysis?.commands.some(
+    command =>
+      command.commandType === 'loadLabware' &&
+      command.result?.labwareId === selectedLabware?.id &&
+      typeof command.params.location === 'object' &&
+      ('moduleId' in command.params.location ||
+        'labwareId' in command.params.location)
+  )
 
   let location: JSX.Element | string | null = null
-  let topLabwareId: string | null = null
   if (
     selectedLabware != null &&
     typeof selectedLabware.location === 'object' &&
@@ -178,17 +187,6 @@ export function ProtocolSetupLabware({
         module.moduleId === selectedLabware.location.moduleId
     )
     if (matchedModule != null) {
-      topLabwareId =
-        mostRecentAnalysis?.commands.find(
-          (command): command is LoadLabwareRunTimeCommand => {
-            return (
-              command.commandType === 'loadLabware' &&
-              typeof command.params.location === 'object' &&
-              'moduleId' in command.params.location &&
-              command.params.location.moduleId === matchedModule.moduleId
-            )
-          }
-        )?.result?.labwareId ?? null
       location = <DeckInfoLabel deckLabel={matchedModule?.slotName} />
     }
   } else if (
@@ -203,17 +201,6 @@ export function ProtocolSetupLabware({
         command.result?.labwareId === adapterId
     )?.params.location
     if (adapterLocation != null && adapterLocation !== 'offDeck') {
-      topLabwareId =
-        mostRecentAnalysis?.commands.find(
-          (command): command is LoadLabwareRunTimeCommand => {
-            return (
-              command.commandType === 'loadLabware' &&
-              typeof command.params.location === 'object' &&
-              'labwareId' in command.params.location &&
-              command.params.location.labwareId === adapterId
-            )
-          }
-        )?.result?.labwareId ?? null
       if ('slotName' in adapterLocation) {
         location = <DeckInfoLabel deckLabel={adapterLocation.slotName} />
       } else if ('moduleId' in adapterLocation) {
@@ -232,7 +219,7 @@ export function ProtocolSetupLabware({
       {createPortal(
         <>
           {showLabwareDetailsModal &&
-          topLabwareId == null &&
+          !selectedLabwareIsTopOfStack &&
           selectedLabware != null ? (
             <Modal
               onOutsideClick={() => {
@@ -357,9 +344,11 @@ export function ProtocolSetupLabware({
             })}
           </>
         )}
-        {showLabwareDetailsModal && topLabwareId != null ? (
+        {showLabwareDetailsModal &&
+        selectedLabware != null &&
+        selectedLabwareIsTopOfStack ? (
           <LabwareStackModal
-            labwareIdTop={topLabwareId}
+            labwareIdTop={selectedLabware?.id}
             runId={runId}
             closeModal={() => {
               setSelectedLabware(null)
diff --git a/components/src/hardware-sim/Labware/LabwareStackRender.tsx b/components/src/hardware-sim/Labware/LabwareStackRender.tsx
index d9184e327f0..6b1b9aec35d 100644
--- a/components/src/hardware-sim/Labware/LabwareStackRender.tsx
+++ b/components/src/hardware-sim/Labware/LabwareStackRender.tsx
@@ -1,6 +1,6 @@
 import * as React from 'react'
 import { WellLabels, StaticLabware } from './labwareInternals'
-import { LabwareAdapter } from './LabwareAdapter'
+import { LabwareAdapter, labwareAdapterLoadNames } from './LabwareAdapter'
 import { COLORS } from '../../helix-design-system'
 import { Svg } from '../..'
 
@@ -8,7 +8,6 @@ import type { LabwareDefinition2 } from '@opentrons/shared-data'
 import type { HighlightedWellLabels } from './labwareInternals/types'
 import type { LabwareAdapterLoadName } from './LabwareAdapter'
 import type { WellLabelOption } from '../..'
-
 const HIGHLIGHT_COLOR = COLORS.blue30
 const STROKE_WIDTH = 1
 const SKEW_ANGLE_DEGREES = 30
@@ -87,7 +86,9 @@ export const LabwareStackRender = (
     definitionBottom.parameters.loadName === 'opentrons_flex_96_tiprack_adapter'
   ) {
     const { xDimension, yDimension } = definitionTop.dimensions
-    const isTopAdapter = definitionTop.metadata.displayCategory === 'adapter'
+    const isTopAdapter = labwareAdapterLoadNames.includes(
+      definitionTop.parameters.loadName
+    )
 
     return isTopAdapter ? (
       // adapter render