Skip to content

Commit

Permalink
Add exit prevention screen
Browse files Browse the repository at this point in the history
  • Loading branch information
smb2268 committed May 2, 2024
1 parent 3e1ba3e commit f4ca1c2
Show file tree
Hide file tree
Showing 6 changed files with 139 additions and 28 deletions.
54 changes: 54 additions & 0 deletions app/src/organisms/QuickTransferFlow/ConfirmExitModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import * as React from 'react'
import { useTranslation } from 'react-i18next'
import {
SPACING,
COLORS,
StyledText,
Flex,
DIRECTION_COLUMN,
TYPOGRAPHY,
} from '@opentrons/components'
import { Modal } from '../../molecules/Modal'
import { SmallButton } from '../../atoms/buttons'

interface ConfirmExitModalProps {
confirmExit: () => void
cancelExit: () => void
}

export const ConfirmExitModal = (props: ConfirmExitModalProps): JSX.Element => {
const { i18n, t } = useTranslation(['quick_transfer', 'shared'])

return (
<Modal
header={{
title: t('exit_quick_transfer'),
iconName: 'alert-circle',
iconColor: COLORS.yellow50,
}}
>
<Flex
flexDirection={DIRECTION_COLUMN}
gridGap={SPACING.spacing10}
width="100%"
>
<StyledText css={TYPOGRAPHY.bodyTextRegular}>
{t('lose_all_progress')}
</StyledText>
<Flex gridGap={SPACING.spacing8}>
<SmallButton
width="50%"
buttonText={i18n.format(t('shared:cancel'), 'capitalize')}
onClick={props.cancelExit}
/>
<SmallButton
width="50%"
buttonText={i18n.format(t('shared:delete'), 'capitalize')}
onClick={props.confirmExit}
buttonType="alert"
/>
</Flex>
</Flex>
</Modal>
)
}
11 changes: 6 additions & 5 deletions app/src/organisms/QuickTransferFlow/SelectDestLabware.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ export function SelectDestLabware(
): JSX.Element | null {
const { onNext, onBack, exitButtonProps, state, dispatch } = props
const { i18n, t } = useTranslation(['quick_transfer', 'shared'])
if (state.pipette == null) return null
const labwareDisplayCategoryFilters: LabwareFilter[] = [
'all',
'wellPlate',
Expand All @@ -46,15 +45,17 @@ export function SelectDestLabware(
const [selectedCategory, setSelectedCategory] = React.useState<LabwareFilter>(
'all'
)
const [selectedLabware, setSelectedLabware] = React.useState<
LabwareDefinition2 | 'source' | undefined
>(state.destination)

if (state.pipette == null) return null

const compatibleLabwareDefinitions = getCompatibleLabwareByCategory(
state.pipette.channels,
selectedCategory
)

const [selectedLabware, setSelectedLabware] = React.useState<
LabwareDefinition2 | 'source' | undefined
>(state.destination)

const handleClickNext = (): void => {
// the button will be disabled if this values is null
if (selectedLabware != null) {
Expand Down
13 changes: 7 additions & 6 deletions app/src/organisms/QuickTransferFlow/SelectSourceLabware.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,28 +34,29 @@ export function SelectSourceLabware(
): JSX.Element | null {
const { onNext, onBack, exitButtonProps, state, dispatch } = props
const { i18n, t } = useTranslation(['quick_transfer', 'shared'])
if (state.pipette == null) return null
const labwareDisplayCategoryFilters: LabwareFilter[] = [
'all',
'wellPlate',
'reservoir',
]
if (state.pipette.channels === 1) {
if (state.pipette?.channels === 1) {
labwareDisplayCategoryFilters.push('tubeRack')
}
const [selectedCategory, setSelectedCategory] = React.useState<LabwareFilter>(
'all'
)

const [selectedLabware, setSelectedLabware] = React.useState<
LabwareDefinition2 | undefined
>(state.source)

if (state.pipette == null) return null

const compatibleLabwareDefinitions = getCompatibleLabwareByCategory(
state.pipette.channels,
selectedCategory
)

const [selectedLabware, setSelectedLabware] = React.useState<
LabwareDefinition2 | undefined
>(state.source)

const handleClickNext = (): void => {
// the button will be disabled if this values is null
if (selectedLabware != null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import * as React from 'react'
import { fireEvent, screen } from '@testing-library/react'
import { describe, it, expect, afterEach, vi, beforeEach } from 'vitest'

import { renderWithProviders } from '../../../__testing-utils__'
import { i18n } from '../../../i18n'
import { ConfirmExitModal } from '../ConfirmExitModal'

const render = (props: React.ComponentProps<typeof ConfirmExitModal>) => {
return renderWithProviders(<ConfirmExitModal {...props} />, {
i18nInstance: i18n,
})
}

describe('ConfirmExitModal', () => {
let props: React.ComponentProps<typeof ConfirmExitModal>

beforeEach(() => {
props = {
confirmExit: vi.fn(),
cancelExit: vi.fn(),
}
})
afterEach(() => {
vi.resetAllMocks()
})

it('renders the create new transfer screen and header', () => {
render(props)
screen.getByText('Exit quick transfer?')
screen.getByText('You will lose all progress on this quick transfer.')
})
it('renders exit and cancel buttons and they work as expected', () => {
render(props)
const cancelBtn = screen.getByText('Cancel')
fireEvent.click(cancelBtn)
expect(props.cancelExit).toHaveBeenCalled()
const deleteBtn = screen.getByText('Delete')
fireEvent.click(deleteBtn)
expect(props.confirmExit).toHaveBeenCalled()
})
})
37 changes: 26 additions & 11 deletions app/src/organisms/QuickTransferFlow/index.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import * as React from 'react'
import { useHistory } from 'react-router-dom'
import { useTranslation } from 'react-i18next'
import { StepMeter, POSITION_STICKY } from '@opentrons/components'
import {
useConditionalConfirm,
StepMeter,
POSITION_STICKY,
} from '@opentrons/components'
import { SmallButton } from '../../atoms/buttons'
import { ConfirmExitModal } from './ConfirmExitModal'
import { CreateNewTransfer } from './CreateNewTransfer'
import { SelectPipette } from './SelectPipette'
import { SelectTipRack } from './SelectTipRack'
Expand All @@ -27,12 +32,16 @@ export const QuickTransferFlow = (): JSX.Element => {
)
const [currentStep, setCurrentStep] = React.useState(1)

const {
confirm: confirmExit,
showConfirmation: showConfirmExit,
cancel: cancelExit,
} = useConditionalConfirm(() => history.push('protocols'), true)

const exitButtonProps: React.ComponentProps<typeof SmallButton> = {
buttonType: 'tertiaryLowLight',
buttonText: i18n.format(t('shared:exit'), 'capitalize'),
onClick: () => {
history.push('protocols')
},
onClick: confirmExit,
}

React.useEffect(() => {
Expand Down Expand Up @@ -128,13 +137,19 @@ export const QuickTransferFlow = (): JSX.Element => {

return (
<>
<StepMeter
totalSteps={QUICK_TRANSFER_WIZARD_STEPS}
currentStep={currentStep}
position={POSITION_STICKY}
top="0"
/>
{modalContent}
{showConfirmExit ? (
<ConfirmExitModal confirmExit={confirmExit} cancelExit={cancelExit} />
) : (
<>
<StepMeter
totalSteps={QUICK_TRANSFER_WIZARD_STEPS}
currentStep={currentStep}
position={POSITION_STICKY}
top="0"
/>
{modalContent}
</>
)}
</>
)
}
10 changes: 4 additions & 6 deletions app/src/organisms/QuickTransferFlow/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,12 +158,10 @@ export function getVolumeLimits(

const destLabwareVolume = Math.min(
...state.destinationWells.map(well => {
{
if (state.source == null || state.destination == null) return 0
return state.destination === 'source'
? state.source.wells[well].totalLiquidVolume
: state.destination.wells[well].totalLiquidVolume
}
if (state.source == null || state.destination == null) return 0
return state.destination === 'source'
? state.source.wells[well].totalLiquidVolume
: state.destination.wells[well].totalLiquidVolume
})
)
let maxVolume = maxPipetteVolume
Expand Down

0 comments on commit f4ca1c2

Please sign in to comment.