@@ -13,7 +13,13 @@ import {
1313 isAddressableAreaStandardSlot ,
1414 THERMOCYCLER_MODULE_TYPE ,
1515} from '@opentrons/shared-data'
16- import { getSlotInLocationStack } from '@opentrons/step-generation'
16+ import {
17+ FAKE_HOPPER_LOCATION_MAP ,
18+ getIsSlotAHopper ,
19+ getSlotInLocationStack ,
20+ } from '@opentrons/step-generation'
21+
22+ import { HOPPER_LABWARE_X_OFFSET } from '/protocol-designer/constants'
1723
1824import { LabwareOnDeck } from '../../../components/organisms'
1925import { getSlotsWithCollisions } from '../../../components/organisms/utils'
@@ -53,6 +59,7 @@ import type {
5359 DeckSlotId ,
5460} from '@opentrons/shared-data'
5561import type {
62+ HopperLocationMapKey ,
5663 ModuleTemporalProperties ,
5764 ThermocyclerModuleState ,
5865} from '@opentrons/step-generation'
@@ -86,6 +93,7 @@ export function DeckSetupDetails(props: DeckSetupDetailsProps): JSX.Element {
8693 showGen1MultichannelCollisionWarnings,
8794 stagingAreaCutoutIds,
8895 } = props
96+ const { labware : activeLabware } = activeDeckSetup
8997 const robotType = useSelector ( getRobotType )
9098 const slotIdsBlockedBySpanning = getSlotIdsBlockedBySpanningForThermocycler (
9199 activeDeckSetup ,
@@ -118,7 +126,7 @@ export function DeckSetupDetails(props: DeckSetupDetailsProps): JSX.Element {
118126 draggedLabware,
119127 } )
120128 const swapBlockedAdapter = getSwapBlockedAdapter ( {
121- labwareById : activeDeckSetup . labware ,
129+ labwareById : activeLabware ,
122130 hoveredLabware,
123131 draggedLabware,
124132 } )
@@ -134,6 +142,7 @@ export function DeckSetupDetails(props: DeckSetupDetailsProps): JSX.Element {
134142 createdModuleForSlot,
135143 preSelectedFixture,
136144 slotPosition,
145+ isSlotAHopper,
137146 } = useMemo ( ( ) => {
138147 return getSlotInformation ( {
139148 deckSetup : activeDeckSetup ,
@@ -142,8 +151,7 @@ export function DeckSetupDetails(props: DeckSetupDetailsProps): JSX.Element {
142151 } )
143152 } , [ activeDeckSetup , selectedZoomInSlot ] )
144153
145- const createdTopLabwareForSlot =
146- activeDeckSetup . labware [ createdStackForSlot [ 0 ] ]
154+ const createdTopLabwareForSlot = activeLabware [ createdStackForSlot [ 0 ] ]
147155 const amount = createdStackForSlot ?. length ?? 1
148156 // initiate the slot's info
149157 useEffect ( ( ) => {
@@ -171,11 +179,22 @@ export function DeckSetupDetails(props: DeckSetupDetailsProps): JSX.Element {
171179 selectedZoomInSlot ,
172180 ] )
173181
174- const allLabware = Object . values ( activeDeckSetup . labware )
182+ const allLabware = Object . values ( activeLabware )
175183
176184 const allModules : ModuleOnDeck [ ] = values ( activeDeckSetup . modules )
177- const menuListSlotPosition = getPositionFromSlotId ( menuListId ?? '' , deckDef )
178-
185+ const isMenuListIdForHopper =
186+ menuListId != null && getIsSlotAHopper ( menuListId )
187+ const adjustedMenuListId = isMenuListIdForHopper
188+ ? FAKE_HOPPER_LOCATION_MAP [ menuListId as HopperLocationMapKey ]
189+ : menuListId
190+ const menuListSlotPosition =
191+ adjustedMenuListId != null
192+ ? getPositionFromSlotId (
193+ adjustedMenuListId as string ,
194+ deckDef ,
195+ ...( isMenuListIdForHopper ? [ HOPPER_LABWARE_X_OFFSET ] : [ ] )
196+ )
197+ : null
179198 const multichannelWarningSlotIds : AddressableAreaName [ ] =
180199 showGen1MultichannelCollisionWarnings
181200 ? getSlotsWithCollisions ( deckDef , allModules )
@@ -186,7 +205,7 @@ export function DeckSetupDetails(props: DeckSetupDetailsProps): JSX.Element {
186205 ? getAdjacentLabware (
187206 preSelectedFixture ,
188207 selectedSlot . cutout ,
189- activeDeckSetup . labware
208+ activeLabware
190209 )
191210 : null
192211
@@ -245,10 +264,8 @@ export function DeckSetupDetails(props: DeckSetupDetailsProps): JSX.Element {
245264 }
246265 }
247266
248- const { topMostId, rightBelowTopId } = getLabwaresOnModuleFromStack (
249- moduleOnDeck . id ,
250- allLabware
251- )
267+ const { topMostId, rightBelowTopId, hopperTopMostId } =
268+ getLabwaresOnModuleFromStack ( moduleOnDeck . id , allLabware )
252269 const labwareInterfaceBoundingBox = {
253270 xDimension : moduleDef . dimensions . labwareInterfaceXDimension ?? 0 ,
254271 yDimension : moduleDef . dimensions . labwareInterfaceYDimension ?? 0 ,
@@ -273,11 +290,9 @@ export function DeckSetupDetails(props: DeckSetupDetailsProps): JSX.Element {
273290 }
274291 : tempInnerProps
275292 const labwareOnModule =
276- topMostId != null ? activeDeckSetup . labware [ topMostId ] : null
293+ topMostId != null ? activeLabware [ topMostId ] : null
277294 const labwareRightBelowTopMostLabware =
278- rightBelowTopId != null
279- ? activeDeckSetup . labware [ rightBelowTopId ]
280- : null
295+ rightBelowTopId != null ? activeLabware [ rightBelowTopId ] : null
281296 const isAdapter = labwareOnModule ?. def . allowedRoles ?. includes ( 'adapter' )
282297
283298 return moduleOnDeck . slot !== selectedSlot . slot ? (
@@ -299,6 +314,34 @@ export function DeckSetupDetails(props: DeckSetupDetailsProps): JSX.Element {
299314 : 'offsetToSlot'
300315 }
301316 >
317+ { hopperTopMostId != null ? (
318+ < >
319+ < LabwareOnDeck
320+ x = { HOPPER_LABWARE_X_OFFSET }
321+ y = { 0 }
322+ labwareOnDeck = { activeLabware [ hopperTopMostId ] }
323+ />
324+ < HighlightLabware
325+ labwareOnDeck = { activeLabware [ hopperTopMostId ] }
326+ position = { [ HOPPER_LABWARE_X_OFFSET , 0 , 0 ] }
327+ isZoomed = { selectedZoomInSlot != null }
328+ />
329+ < LabwareControls
330+ terminalItemId = { terminalItemId }
331+ itemId = { `hopper${ slotId } ` }
332+ setHover = { setHover }
333+ setShowMenuListForId = { setShowMenuListForId }
334+ hover = { hover }
335+ slotPosition = { [ HOPPER_LABWARE_X_OFFSET , 0 , 0 ] } // Module Component already handles nested positioning
336+ setHoveredLabware = { setHoveredLabware }
337+ setDraggedLabware = { setDraggedLabware }
338+ // TODO: disallow the ability to drag/drop labware from the hopper and shuttle
339+ swapBlocked = { false }
340+ labwareOnDeck = { activeLabware [ hopperTopMostId ] }
341+ isSelected = { selectedZoomInSlot != null }
342+ />
343+ </ >
344+ ) : null }
302345 { labwareOnModule != null &&
303346 ! isLabwareOccludedByThermocyclerLid ? (
304347 < >
@@ -381,6 +424,26 @@ export function DeckSetupDetails(props: DeckSetupDetailsProps): JSX.Element {
381424 addEquipment = { addEquipment }
382425 />
383426 ) : null }
427+ { hopperTopMostId == null &&
428+ moduleOnDeck . type === FLEX_STACKER_MODULE_TYPE ? (
429+ < SlotControls
430+ terminalItemId = { terminalItemId }
431+ itemId = { `hopper${ slotId } ` }
432+ key = { `${ moduleOnDeck . slot } _flexHopper` }
433+ slotPosition = { [ HOPPER_LABWARE_X_OFFSET , 0 , 0 ] }
434+ slotBoundingBox = { labwareInterfaceBoundingBox }
435+ moduleType = { moduleOnDeck . type }
436+ handleDragHover = { handleHoverEmptySlot }
437+ slotId = { moduleOnDeck . id }
438+ hover = { hover }
439+ setHover = { setHover }
440+ setShowMenuListForId = { setShowMenuListForId }
441+ isSelected = { selectedZoomInSlot != null }
442+ deckDef = { deckDef }
443+ stagingAreaAddressableAreas = { [ ] }
444+ addEquipment = { addEquipment }
445+ />
446+ ) : null }
384447 </ Module >
385448 </ Fragment >
386449 ) : null
@@ -431,6 +494,7 @@ export function DeckSetupDetails(props: DeckSetupDetailsProps): JSX.Element {
431494 const moduleOnSlot = Object . values ( activeDeckSetup . modules ) . find (
432495 module => module . slot === addressableArea . id
433496 )
497+
434498 return (
435499 < SlotControls
436500 terminalItemId = { terminalItemId }
@@ -465,7 +529,7 @@ export function DeckSetupDetails(props: DeckSetupDetailsProps): JSX.Element {
465529 }
466530 const slot = getSlotInLocationStack ( labware . stack )
467531 const labwareAmount = labware . stack . reduce (
468- ( amount , item ) => amount + ( activeDeckSetup . labware [ item ] ? 1 : 0 ) ,
532+ ( amount , item ) => amount + ( activeLabware [ item ] ? 1 : 0 ) ,
469533 0
470534 )
471535 const isTopLabware = labware . stack [ 0 ] === labware . id
@@ -649,6 +713,7 @@ export function DeckSetupDetails(props: DeckSetupDetailsProps): JSX.Element {
649713 deckDef = { deckDef }
650714 robotType = { robotType }
651715 slotPosition = { slotPosition }
716+ isSlotAHopper = { isSlotAHopper }
652717 />
653718
654719 { /* slot overflow menu */ }
0 commit comments