From f798a956aa9242343f38b39f4549f54114afdba6 Mon Sep 17 00:00:00 2001 From: smb2268 Date: Wed, 15 May 2024 16:34:46 -0400 Subject: [PATCH] feat(app): setup advanced settings/tip management state for quick transfer fix PLAT-227 --- .../organisms/QuickTransferFlow/Overview.tsx | 14 +- .../QuickTransferFlow/SelectDestLabware.tsx | 4 +- .../QuickTransferFlow/SelectDestWells.tsx | 4 +- .../QuickTransferFlow/SelectPipette.tsx | 4 +- .../QuickTransferFlow/SelectSourceLabware.tsx | 4 +- .../QuickTransferFlow/SelectSourceWells.tsx | 4 +- .../QuickTransferFlow/SelectTipRack.tsx | 4 +- .../QuickTransferFlow/SummaryAndSettings.tsx | 20 +- .../QuickTransferFlow/VolumeEntry.tsx | 4 +- .../__tests__/Overview.test.tsx | 18 +- .../__tests__/SummaryAndSettings.test.tsx | 15 ++ .../QuickTransferFlow/__tests__/utils.test.ts | 4 +- .../organisms/QuickTransferFlow/constants.ts | 18 ++ app/src/organisms/QuickTransferFlow/index.tsx | 8 +- app/src/organisms/QuickTransferFlow/types.ts | 138 ++++++++++++- app/src/organisms/QuickTransferFlow/utils.ts | 181 +++++++++++++++++- 16 files changed, 398 insertions(+), 46 deletions(-) diff --git a/app/src/organisms/QuickTransferFlow/Overview.tsx b/app/src/organisms/QuickTransferFlow/Overview.tsx index 29fdd45696c..94a33b24852 100644 --- a/app/src/organisms/QuickTransferFlow/Overview.tsx +++ b/app/src/organisms/QuickTransferFlow/Overview.tsx @@ -13,10 +13,10 @@ import { import { ListItem } from '../../atoms/ListItem' import { CONSOLIDATE, DISTRIBUTE } from './constants' -import type { QuickTransferSetupState } from './types' +import type { QuickTransferSummaryState } from './types' interface OverviewProps { - state: QuickTransferSetupState + state: QuickTransferSummaryState } export function Overview(props: OverviewProps): JSX.Element | null { @@ -33,18 +33,18 @@ export function Overview(props: OverviewProps): JSX.Element | null { const displayItems = [ { option: t('pipette'), - value: state.pipette?.displayName, + value: state.pipette.displayName, }, { option: t('source_labware'), - value: state.source?.metadata.displayName, + value: state.sourceLabware.metadata.displayName, }, { option: t('destination_labware'), value: - state.destination === 'source' - ? state.source?.metadata.displayName - : state.destination?.metadata.displayName, + state.destinationLabware === 'source' + ? state.sourceLabware.metadata.displayName + : state.destinationLabware.metadata.displayName, }, { option: transferCopy, diff --git a/app/src/organisms/QuickTransferFlow/SelectDestLabware.tsx b/app/src/organisms/QuickTransferFlow/SelectDestLabware.tsx index c5722fba863..5cc42cfaa97 100644 --- a/app/src/organisms/QuickTransferFlow/SelectDestLabware.tsx +++ b/app/src/organisms/QuickTransferFlow/SelectDestLabware.tsx @@ -18,7 +18,7 @@ import type { LabwareDefinition2 } from '@opentrons/shared-data' import type { SmallButton } from '../../atoms/buttons' import type { LabwareFilter } from '../../pages/Labware/types' import type { - QuickTransferSetupState, + QuickTransferWizardState, QuickTransferWizardAction, } from './types' @@ -26,7 +26,7 @@ interface SelectDestLabwareProps { onNext: () => void onBack: () => void exitButtonProps: React.ComponentProps - state: QuickTransferSetupState + state: QuickTransferWizardState dispatch: React.Dispatch } diff --git a/app/src/organisms/QuickTransferFlow/SelectDestWells.tsx b/app/src/organisms/QuickTransferFlow/SelectDestWells.tsx index beef6d55e39..9ac3c3430ce 100644 --- a/app/src/organisms/QuickTransferFlow/SelectDestWells.tsx +++ b/app/src/organisms/QuickTransferFlow/SelectDestWells.tsx @@ -6,7 +6,7 @@ import { ChildNavigation } from '../ChildNavigation' import type { SmallButton } from '../../atoms/buttons' import type { - QuickTransferSetupState, + QuickTransferWizardState, QuickTransferWizardAction, } from './types' @@ -14,7 +14,7 @@ interface SelectDestWellsProps { onNext: () => void onBack: () => void exitButtonProps: React.ComponentProps - state: QuickTransferSetupState + state: QuickTransferWizardState dispatch: React.Dispatch } diff --git a/app/src/organisms/QuickTransferFlow/SelectPipette.tsx b/app/src/organisms/QuickTransferFlow/SelectPipette.tsx index 152bdf1d7aa..98042f1e361 100644 --- a/app/src/organisms/QuickTransferFlow/SelectPipette.tsx +++ b/app/src/organisms/QuickTransferFlow/SelectPipette.tsx @@ -15,7 +15,7 @@ import { ChildNavigation } from '../ChildNavigation' import type { PipetteData, Mount } from '@opentrons/api-client' import type { SmallButton } from '../../atoms/buttons' import type { - QuickTransferSetupState, + QuickTransferWizardState, QuickTransferWizardAction, } from './types' @@ -23,7 +23,7 @@ interface SelectPipetteProps { onNext: () => void onBack: () => void exitButtonProps: React.ComponentProps - state: QuickTransferSetupState + state: QuickTransferWizardState dispatch: React.Dispatch } diff --git a/app/src/organisms/QuickTransferFlow/SelectSourceLabware.tsx b/app/src/organisms/QuickTransferFlow/SelectSourceLabware.tsx index 21b98cb44fd..3524d7dd3c7 100644 --- a/app/src/organisms/QuickTransferFlow/SelectSourceLabware.tsx +++ b/app/src/organisms/QuickTransferFlow/SelectSourceLabware.tsx @@ -18,7 +18,7 @@ import type { LabwareDefinition2 } from '@opentrons/shared-data' import type { SmallButton } from '../../atoms/buttons' import type { LabwareFilter } from '../../pages/Labware/types' import type { - QuickTransferSetupState, + QuickTransferWizardState, QuickTransferWizardAction, } from './types' @@ -26,7 +26,7 @@ interface SelectSourceLabwareProps { onNext: () => void onBack: () => void exitButtonProps: React.ComponentProps - state: QuickTransferSetupState + state: QuickTransferWizardState dispatch: React.Dispatch } diff --git a/app/src/organisms/QuickTransferFlow/SelectSourceWells.tsx b/app/src/organisms/QuickTransferFlow/SelectSourceWells.tsx index cd82278a66b..0c8b6aafd37 100644 --- a/app/src/organisms/QuickTransferFlow/SelectSourceWells.tsx +++ b/app/src/organisms/QuickTransferFlow/SelectSourceWells.tsx @@ -6,7 +6,7 @@ import { ChildNavigation } from '../ChildNavigation' import type { SmallButton } from '../../atoms/buttons' import type { - QuickTransferSetupState, + QuickTransferWizardState, QuickTransferWizardAction, } from './types' @@ -14,7 +14,7 @@ interface SelectSourceWellsProps { onNext: () => void onBack: () => void exitButtonProps: React.ComponentProps - state: QuickTransferSetupState + state: QuickTransferWizardState dispatch: React.Dispatch } diff --git a/app/src/organisms/QuickTransferFlow/SelectTipRack.tsx b/app/src/organisms/QuickTransferFlow/SelectTipRack.tsx index 462e13d1eae..acd5e90b054 100644 --- a/app/src/organisms/QuickTransferFlow/SelectTipRack.tsx +++ b/app/src/organisms/QuickTransferFlow/SelectTipRack.tsx @@ -8,7 +8,7 @@ import { ChildNavigation } from '../ChildNavigation' import type { LabwareDefinition2 } from '@opentrons/shared-data' import type { SmallButton } from '../../atoms/buttons' import type { - QuickTransferSetupState, + QuickTransferWizardState, QuickTransferWizardAction, } from './types' @@ -16,7 +16,7 @@ interface SelectTipRackProps { onNext: () => void onBack: () => void exitButtonProps: React.ComponentProps - state: QuickTransferSetupState + state: QuickTransferWizardState dispatch: React.Dispatch } diff --git a/app/src/organisms/QuickTransferFlow/SummaryAndSettings.tsx b/app/src/organisms/QuickTransferFlow/SummaryAndSettings.tsx index 3cfd0063a68..85303cd4397 100644 --- a/app/src/organisms/QuickTransferFlow/SummaryAndSettings.tsx +++ b/app/src/organisms/QuickTransferFlow/SummaryAndSettings.tsx @@ -13,20 +13,21 @@ import { import { TabbedButton } from '../../atoms/buttons' import { ChildNavigation } from '../ChildNavigation' import { Overview } from './Overview' +import { getInitialSummaryState, quickTransferSummaryReducer } from './utils' import type { SmallButton } from '../../atoms/buttons' -import type { QuickTransferSetupState } from './types' +import type { QuickTransferWizardState } from './types' interface SummaryAndSettingsProps { onNext: () => void exitButtonProps: React.ComponentProps - state: QuickTransferSetupState + state: QuickTransferWizardState } export function SummaryAndSettings( props: SummaryAndSettingsProps ): JSX.Element | null { - const { onNext, exitButtonProps, state } = props + const { onNext, exitButtonProps, state: wizardFlowState } = props const { t } = useTranslation(['quick_transfer', 'shared']) const displayCategory: string[] = [ 'overview', @@ -36,11 +37,22 @@ export function SummaryAndSettings( const [selectedCategory, setSelectedCategory] = React.useState( 'overview' ) + // if any value from the wizard flow hasn't been set, return null + // this should never happen but allows us to strictly type summary state + // @ts-expect-error figure out how to make this type non-null + const initialSummaryState = getInitialSummaryState(wizardFlowState) + const [state] = React.useReducer( + quickTransferSummaryReducer, + initialSummaryState + ) + if (Object.values(wizardFlowState).some(value => value == null)) { + return null + } return ( void onBack: () => void exitButtonProps: React.ComponentProps - state: QuickTransferSetupState + state: QuickTransferWizardState dispatch: React.Dispatch } diff --git a/app/src/organisms/QuickTransferFlow/__tests__/Overview.test.tsx b/app/src/organisms/QuickTransferFlow/__tests__/Overview.test.tsx index e324b22c2ff..6132cd40928 100644 --- a/app/src/organisms/QuickTransferFlow/__tests__/Overview.test.tsx +++ b/app/src/organisms/QuickTransferFlow/__tests__/Overview.test.tsx @@ -21,19 +21,19 @@ describe('Overview', () => { pipette: { displayName: 'Pipette display name', } as any, - source: { + sourceLabware: { metadata: { displayName: 'Source labware name', }, } as any, - destination: { + destinationLabware: { metadata: { displayName: 'Destination labware name', }, } as any, transferType: 'transfer', volume: 25, - }, + } as any, } }) afterEach(() => { @@ -57,19 +57,19 @@ describe('Overview', () => { pipette: { displayName: 'Pipette display name', } as any, - source: { + sourceLabware: { metadata: { displayName: 'Source labware name', }, } as any, - destination: { + destinationLabware: { metadata: { displayName: 'Destination labware name', }, } as any, transferType: 'consolidate', volume: 25, - }, + } as any, } render(props) screen.getByText('Aspirate volume per well') @@ -80,19 +80,19 @@ describe('Overview', () => { pipette: { displayName: 'Pipette display name', } as any, - source: { + sourceLabware: { metadata: { displayName: 'Source labware name', }, } as any, - destination: { + destinationLabware: { metadata: { displayName: 'Destination labware name', }, } as any, transferType: 'distribute', volume: 25, - }, + } as any, } render(props) screen.getByText('Dispense volume per well') diff --git a/app/src/organisms/QuickTransferFlow/__tests__/SummaryAndSettings.test.tsx b/app/src/organisms/QuickTransferFlow/__tests__/SummaryAndSettings.test.tsx index b8d30c5d299..614f5160e9c 100644 --- a/app/src/organisms/QuickTransferFlow/__tests__/SummaryAndSettings.test.tsx +++ b/app/src/organisms/QuickTransferFlow/__tests__/SummaryAndSettings.test.tsx @@ -8,6 +8,13 @@ import { SummaryAndSettings } from '../SummaryAndSettings' import { Overview } from '../Overview' vi.mock('../Overview') +vi.mock('../utils', async () => { + const actual = await vi.importActual('../utils') + return { + ...actual, + getInitialSummaryState: vi.fn(), + } +}) const render = (props: React.ComponentProps) => { return renderWithProviders(, { @@ -27,6 +34,14 @@ describe('SummaryAndSettings', () => { onClick: vi.fn(), }, state: { + pipette: {} as any, + mount: 'left', + tipRack: {} as any, + source: {} as any, + sourceWells: ['A1'], + destination: {} as any, + destinationWells: ['A1'], + transferType: 'transfer', volume: 25, }, } diff --git a/app/src/organisms/QuickTransferFlow/__tests__/utils.test.ts b/app/src/organisms/QuickTransferFlow/__tests__/utils.test.ts index 7cb4c7e1495..e8ad3a444fd 100644 --- a/app/src/organisms/QuickTransferFlow/__tests__/utils.test.ts +++ b/app/src/organisms/QuickTransferFlow/__tests__/utils.test.ts @@ -6,10 +6,10 @@ import { NINETY_SIX_CHANNEL_COMPATIBLE_LABWARE, } from '../constants' -import type { QuickTransferSetupState } from '../types' +import type { QuickTransferWizardState } from '../types' describe('getVolumeLimits', () => { - const state: QuickTransferSetupState = { + const state: QuickTransferWizardState = { pipette: { liquids: [ { diff --git a/app/src/organisms/QuickTransferFlow/constants.ts b/app/src/organisms/QuickTransferFlow/constants.ts index c7f58103bbb..0d5786fb4ff 100644 --- a/app/src/organisms/QuickTransferFlow/constants.ts +++ b/app/src/organisms/QuickTransferFlow/constants.ts @@ -6,6 +6,24 @@ export const ACTIONS = { SET_DEST_LABWARE: 'SET_DEST_LABWARE', SET_DEST_WELLS: 'SET_DEST_WELLS', SET_VOLUME: 'SET_VOLUME', + SUMMARY_SETUP: 'SUMMARY_SETUP', + SET_ASPIRATE_FLOW_RATE: 'SET_ASPIRATE_FLOW_RATE', + SET_DISPENSE_FLOW_RATE: 'SET_DISPENSE_FLOW_RATE', + SET_PIPETTE_PATH: 'SET_PIPETTE_PATH', + SET_ASPIRATE_TIP_POSITION: 'SET_ASPIRATE_TIP_POSITION', + SET_PRE_WET_TIP: 'SET_PRE_WET_TIP', + SET_MIX_ON_ASPIRATE: 'SET_MIX_ON_ASPIRATE', + SET_DELAY_ASPIRATE: 'SET_DELAY_ASPIRATE', + SET_TOUCH_TIP_ASPIRATE: 'SET_TOUCH_TIP_ASPIRATE', + SET_AIR_GAP_ASPIRATE: 'SET_AIR_GAP_ASPIRATE', + SET_DISPENSE_TIP_POSITION: 'SET_DISPENSE_TIP_POSITION', + SET_MIX_ON_DISPENSE: 'SET_MIX_ON_DISPENSE', + SET_DELAY_DISPENSE: 'SET_DELAY_DISPENSE', + SET_TOUCH_TIP_DISPENSE: 'SET_TOUCH_TIP_DISPENSE', + SET_BLOW_OUT: 'SET_BLOW_OUT', + SET_AIR_GAP_DISPENSE: 'SET_AIR_GAP_DISPENSE', + SET_CHANGE_TIP: 'SET_CHANGE_TIP', + SET_DROP_TIP_LOCATION: 'SET_DROP_TIP_LOCATION', } as const export const DISTRIBUTE = 'distribute' diff --git a/app/src/organisms/QuickTransferFlow/index.tsx b/app/src/organisms/QuickTransferFlow/index.tsx index d95c54bd84f..28188133f25 100644 --- a/app/src/organisms/QuickTransferFlow/index.tsx +++ b/app/src/organisms/QuickTransferFlow/index.tsx @@ -16,19 +16,19 @@ import { SelectDestLabware } from './SelectDestLabware' import { SelectDestWells } from './SelectDestWells' import { VolumeEntry } from './VolumeEntry' import { SummaryAndSettings } from './SummaryAndSettings' -import { quickTransferReducer } from './utils' +import { quickTransferWizardReducer } from './utils' import type { SmallButton } from '../../atoms/buttons' -import type { QuickTransferSetupState } from './types' +import type { QuickTransferWizardState } from './types' const QUICK_TRANSFER_WIZARD_STEPS = 8 -const initialQuickTransferState: QuickTransferSetupState = {} +const initialQuickTransferState: QuickTransferWizardState = {} export const QuickTransferFlow = (): JSX.Element => { const history = useHistory() const { i18n, t } = useTranslation(['quick_transfer', 'shared']) const [state, dispatch] = React.useReducer( - quickTransferReducer, + quickTransferWizardReducer, initialQuickTransferState ) const [currentStep, setCurrentStep] = React.useState(0) diff --git a/app/src/organisms/QuickTransferFlow/types.ts b/app/src/organisms/QuickTransferFlow/types.ts index ad6e647021d..4106e007a57 100644 --- a/app/src/organisms/QuickTransferFlow/types.ts +++ b/app/src/organisms/QuickTransferFlow/types.ts @@ -1,8 +1,9 @@ import type { Mount } from '@opentrons/api-client' import type { LabwareDefinition2, PipetteV2Specs } from '@opentrons/shared-data' import type { ACTIONS, CONSOLIDATE, DISTRIBUTE, TRANSFER } from './constants' +import type { ChangeTipOptions } from '@opentrons/step-generation' -export interface QuickTransferSetupState { +export interface QuickTransferWizardState { pipette?: PipetteV2Specs mount?: Mount tipRack?: LabwareDefinition2 @@ -13,6 +14,48 @@ export interface QuickTransferSetupState { transferType?: TransferType volume?: number } +export type PathOption = 'single' | 'multiAspirate' | 'multiDispense' + +export interface QuickTransferSummaryState { + pipette: PipetteV2Specs + mount: Mount + tipRack: LabwareDefinition2 + sourceLabware: LabwareDefinition2 + sourceWells: string[] + destinationLabware: LabwareDefinition2 | 'source' + destinationWells: string[] + transferType: TransferType + volume: number + aspirateFlowRate: number + dispenseFlowRate: number + path: PathOption + tipPositionAspirate: number + preWetTip: boolean + mixOnAspirate?: { + mixVolume: number + repititions: number + } + delayAspirate?: { + delayDuration: number + positionFromBottom: number + } + touchTipAspirate?: number + airGapAspirate?: number + tipPositionDispense: number + mixOnDispense?: { + mixVolume: number + repititions: number + } + delayDispense?: { + delayDuration: number + positionFromBottom: number + } + touchTipDispense?: number + blowOut?: string // trashBin or wasteChute or 'SOURCE_WELL' or 'DEST_WELL' + airGapDispense?: number + changeTip: ChangeTipOptions + dropTipLocation: string // trashBin or wasteChute or tiprack +} export type TransferType = | typeof CONSOLIDATE @@ -28,6 +71,99 @@ export type QuickTransferWizardAction = | SetDestWellsAction | SetVolumeAction +export type QuickTransferSummaryAction = + | SetAspirateFlowRateAction + | SetDispenseFlowRateAction + | SetPipettePath + | SetAspirateTipPosition + | SetPreWetTip + | SetMixOnAspirate + | SetDelayAspirate + | SetTouchTipAspirate + | SetAirGapAspirate + | SetDispenseTipPosition + | SetMixOnDispense + | SetDelayDispense + | SetTouchTipDispense + | SetBlowOut + | SetAirGapDispense + | SetChangeTip + | SetDropTipLocation + +interface SetAspirateFlowRateAction { + type: typeof ACTIONS.SET_ASPIRATE_FLOW_RATE + rate: number +} +interface SetDispenseFlowRateAction { + type: typeof ACTIONS.SET_DISPENSE_FLOW_RATE + rate: number +} +interface SetPipettePath { + type: typeof ACTIONS.SET_PIPETTE_PATH + path: PathOption +} +interface SetAspirateTipPosition { + type: typeof ACTIONS.SET_ASPIRATE_TIP_POSITION + position: number +} +interface SetPreWetTip { + type: typeof ACTIONS.SET_PRE_WET_TIP + preWetTip: boolean +} +interface SetMixOnAspirate { + type: typeof ACTIONS.SET_MIX_ON_ASPIRATE + mixSettings?: { mixVolume: number; repititions: number } +} +interface SetDelayAspirate { + type: typeof ACTIONS.SET_DELAY_ASPIRATE + delaySettings?: { + delayDuration: number + positionFromBottom: number + } +} +interface SetTouchTipAspirate { + type: typeof ACTIONS.SET_TOUCH_TIP_ASPIRATE + position?: number +} +interface SetAirGapAspirate { + type: typeof ACTIONS.SET_AIR_GAP_ASPIRATE + volume?: number +} +interface SetDispenseTipPosition { + type: typeof ACTIONS.SET_DISPENSE_TIP_POSITION + position: number +} +interface SetMixOnDispense { + type: typeof ACTIONS.SET_MIX_ON_DISPENSE + mixSettings?: { mixVolume: number; repititions: number } +} +interface SetDelayDispense { + type: typeof ACTIONS.SET_DELAY_DISPENSE + delaySettings?: { + delayDuration: number + positionFromBottom: number + } +} +interface SetTouchTipDispense { + type: typeof ACTIONS.SET_TOUCH_TIP_DISPENSE + position?: number +} +interface SetBlowOut { + type: typeof ACTIONS.SET_BLOW_OUT + location?: string +} +interface SetAirGapDispense { + type: typeof ACTIONS.SET_AIR_GAP_DISPENSE + volume?: number +} +interface SetChangeTip { + type: typeof ACTIONS.SET_CHANGE_TIP + changeTip: ChangeTipOptions +} +interface SetDropTipLocation { + type: typeof ACTIONS.SET_DROP_TIP_LOCATION + location: string +} interface SelectPipetteAction { type: typeof ACTIONS.SELECT_PIPETTE mount: Mount diff --git a/app/src/organisms/QuickTransferFlow/utils.ts b/app/src/organisms/QuickTransferFlow/utils.ts index d4fe4c56fa3..cfc5f5aa1b7 100644 --- a/app/src/organisms/QuickTransferFlow/utils.ts +++ b/app/src/organisms/QuickTransferFlow/utils.ts @@ -18,17 +18,22 @@ import type { PipetteV2Specs, WellSetHelpers, } from '@opentrons/shared-data' +import type { Mount } from '@opentrons/api-client' import type { - QuickTransferSetupState, + QuickTransferWizardState, + QuickTransferSummaryState, QuickTransferWizardAction, + QuickTransferSummaryAction, TransferType, + PathOption, } from './types' + import type { LabwareFilter } from '../../pages/Labware/types' -export function quickTransferReducer( - state: QuickTransferSetupState, +export function quickTransferWizardReducer( + state: QuickTransferWizardState, action: QuickTransferWizardAction -): QuickTransferSetupState { +): QuickTransferWizardState { switch (action.type) { case 'SELECT_PIPETTE': { return { @@ -110,6 +115,172 @@ export function quickTransferReducer( } } +// sets up the initial summary state with defaults based on selections made +// in the wizard flow +export function getInitialSummaryState(props: { + pipette: PipetteV2Specs + mount: Mount + tipRack: LabwareDefinition2 + source: LabwareDefinition2 + sourceWells: string[] + destination: LabwareDefinition2 | 'source' + destinationWells: string[] + transferType: TransferType + volume: number +}): QuickTransferSummaryState { + const tipVolume = Object.values(props.tipRack.wells)[0].totalLiquidVolume + const tipType = `t${tipVolume}` + const flowRatesForSupportedTip = + props.pipette.liquids.default.supportedTips[tipType] + + const volumeLimits = getVolumeLimits(props) + + let path: PathOption = 'single' + if ( + props.transferType === 'consolidate' && + volumeLimits.max >= props.volume * 2 + ) { + path = 'multiAspirate' + } else if ( + props.transferType === 'distribute' && + volumeLimits.max >= props.volume * 2 + ) { + path = 'multiDispense' + } + + return { + pipette: props.pipette, + mount: props.mount, + tipRack: props.tipRack, + sourceLabware: props.source, + sourceWells: props.sourceWells, + destinationLabware: props.destination, + destinationWells: props.destinationWells, + transferType: props.transferType, + volume: props.volume, + aspirateFlowRate: flowRatesForSupportedTip.defaultAspirateFlowRate.default, + dispenseFlowRate: flowRatesForSupportedTip.defaultDispenseFlowRate.default, + path: path, + tipPositionAspirate: 1, + preWetTip: false, + tipPositionDispense: 1, + // TODO add default logic for change tip depending on path, transfer type, number of tips + changeTip: 'once', + // TODO add default logic for drop tip location depending on deck config + dropTipLocation: 'trashBin', + } +} + +export function quickTransferSummaryReducer( + state: QuickTransferSummaryState, + action: QuickTransferSummaryAction +): QuickTransferSummaryState { + switch (action.type) { + case 'SET_ASPIRATE_FLOW_RATE': { + return { + ...state, + aspirateFlowRate: action.rate, + } + } + case 'SET_DISPENSE_FLOW_RATE': { + return { + ...state, + dispenseFlowRate: action.rate, + } + } + case 'SET_PIPETTE_PATH': { + return { + ...state, + path: action.path, + } + } + case 'SET_ASPIRATE_TIP_POSITION': { + return { + ...state, + tipPositionAspirate: action.position, + } + } + case 'SET_PRE_WET_TIP': { + return { + ...state, + preWetTip: action.preWetTip, + } + } + case 'SET_MIX_ON_ASPIRATE': { + return { + ...state, + mixOnAspirate: action.mixSettings, + } + } + case 'SET_DELAY_ASPIRATE': { + return { + ...state, + delayAspirate: action.delaySettings, + } + } + case 'SET_TOUCH_TIP_ASPIRATE': { + return { + ...state, + touchTipAspirate: action.position, + } + } + case 'SET_AIR_GAP_ASPIRATE': { + return { + ...state, + airGapAspirate: action.volume, + } + } + case 'SET_DISPENSE_TIP_POSITION': { + return { + ...state, + tipPositionDispense: action.position, + } + } + case 'SET_MIX_ON_DISPENSE': { + return { + ...state, + mixOnDispense: action.mixSettings, + } + } + case 'SET_DELAY_DISPENSE': { + return { + ...state, + delayDispense: action.delaySettings, + } + } + case 'SET_TOUCH_TIP_DISPENSE': { + return { + ...state, + touchTipDispense: action.position, + } + } + case 'SET_BLOW_OUT': { + return { + ...state, + blowOut: action.location, + } + } + case 'SET_AIR_GAP_DISPENSE': { + return { + ...state, + airGapDispense: action.volume, + } + } + case 'SET_CHANGE_TIP': { + return { + ...state, + changeTip: action.changeTip, + } + } + case 'SET_DROP_TIP_LOCATION': { + return { + ...state, + dropTipLocation: action.location, + } + } + } +} + export function getCompatibleLabwareByCategory( pipetteChannels: 1 | 8 | 96, category: LabwareFilter @@ -151,7 +322,7 @@ export function getCompatibleLabwareByCategory( } export function getVolumeLimits( - state: QuickTransferSetupState + state: QuickTransferWizardState ): { min: number; max: number } { if ( state.pipette == null ||