-
Notifications
You must be signed in to change notification settings - Fork 180
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(app): add labware selection and volume entry screens (#15074)
- Loading branch information
Showing
18 changed files
with
1,492 additions
and
94 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> | ||
) | ||
} |
147 changes: 147 additions & 0 deletions
147
app/src/organisms/QuickTransferFlow/SelectDestLabware.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
import * as React from 'react' | ||
import { useTranslation } from 'react-i18next' | ||
import { | ||
Flex, | ||
SPACING, | ||
DIRECTION_COLUMN, | ||
DIRECTION_ROW, | ||
COLORS, | ||
POSITION_FIXED, | ||
ALIGN_CENTER, | ||
} from '@opentrons/components' | ||
|
||
import { SmallButton, LargeButton, TabbedButton } from '../../atoms/buttons' | ||
import { ChildNavigation } from '../ChildNavigation' | ||
import { getCompatibleLabwareByCategory } from './utils' | ||
|
||
import type { LabwareDefinition2 } from '@opentrons/shared-data' | ||
import type { | ||
QuickTransferSetupState, | ||
QuickTransferWizardAction, | ||
} from './types' | ||
import { LabwareFilter } from '../../pages/Labware/types' | ||
|
||
interface SelectDestLabwareProps { | ||
onNext: () => void | ||
onBack: () => void | ||
exitButtonProps: React.ComponentProps<typeof SmallButton> | ||
state: QuickTransferSetupState | ||
dispatch: React.Dispatch<QuickTransferWizardAction> | ||
} | ||
|
||
export function SelectDestLabware( | ||
props: SelectDestLabwareProps | ||
): JSX.Element | null { | ||
const { onNext, onBack, exitButtonProps, state, dispatch } = props | ||
const { i18n, t } = useTranslation(['quick_transfer', 'shared']) | ||
const labwareDisplayCategoryFilters: LabwareFilter[] = [ | ||
'all', | ||
'wellPlate', | ||
'reservoir', | ||
] | ||
if (state.pipette?.channels === 1) { | ||
labwareDisplayCategoryFilters.push('tubeRack') | ||
} | ||
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 handleClickNext = (): void => { | ||
// the button will be disabled if this values is null | ||
if (selectedLabware != null) { | ||
dispatch({ | ||
type: 'SET_DEST_LABWARE', | ||
labware: selectedLabware, | ||
}) | ||
onNext() | ||
} | ||
} | ||
return ( | ||
<Flex> | ||
<ChildNavigation | ||
header={t('select_dest_labware')} | ||
buttonText={i18n.format(t('shared:continue'), 'capitalize')} | ||
onClickBack={onBack} | ||
onClickButton={handleClickNext} | ||
secondaryButtonProps={exitButtonProps} | ||
top={SPACING.spacing8} | ||
buttonIsDisabled={selectedLabware == null} | ||
/> | ||
<Flex | ||
flexDirection={DIRECTION_COLUMN} | ||
padding={`${SPACING.spacing16} ${SPACING.spacing60} ${SPACING.spacing40} ${SPACING.spacing60}`} | ||
width="100%" | ||
> | ||
<Flex | ||
gridGap={SPACING.spacing8} | ||
height={SPACING.spacing80} | ||
backgroundColor={COLORS.white} | ||
width="100%" | ||
flexDirection={DIRECTION_ROW} | ||
position={POSITION_FIXED} | ||
top={SPACING.spacing120} | ||
marginBottom={SPACING.spacing24} | ||
alignItems={ALIGN_CENTER} | ||
> | ||
{labwareDisplayCategoryFilters.map(category => ( | ||
<TabbedButton | ||
key={category} | ||
title={category} | ||
isSelected={category === selectedCategory} | ||
onClick={() => setSelectedCategory(category)} | ||
height={SPACING.spacing60} | ||
> | ||
{t(category)} | ||
</TabbedButton> | ||
))} | ||
</Flex> | ||
<Flex | ||
gridGap={SPACING.spacing4} | ||
flexDirection={DIRECTION_COLUMN} | ||
marginTop="175px" | ||
> | ||
{selectedCategory === 'all' && state?.source != null ? ( | ||
<LargeButton | ||
buttonType={ | ||
selectedLabware === 'source' ? 'primary' : 'secondary' | ||
} | ||
onClick={() => { | ||
setSelectedLabware('source') | ||
}} | ||
buttonText={t('source_labware')} | ||
subtext={state.source.metadata.displayName} | ||
/> | ||
) : null} | ||
{compatibleLabwareDefinitions?.map(definition => { | ||
return definition.metadata.displayName != null ? ( | ||
<LargeButton | ||
key={`${selectedCategory}-${definition.metadata.displayName}`} | ||
buttonType={ | ||
selectedLabware !== 'source' && | ||
selectedLabware?.metadata.displayName === | ||
definition.metadata.displayName | ||
? 'primary' | ||
: 'secondary' | ||
} | ||
onClick={() => { | ||
setSelectedLabware(definition) | ||
}} | ||
buttonText={definition.metadata.displayName} | ||
/> | ||
) : null | ||
})} | ||
</Flex> | ||
</Flex> | ||
</Flex> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import * as React from 'react' | ||
import { useTranslation } from 'react-i18next' | ||
import { Flex, SPACING } from '@opentrons/components' | ||
|
||
import { SmallButton } from '../../atoms/buttons' | ||
import { ChildNavigation } from '../ChildNavigation' | ||
|
||
import type { | ||
QuickTransferSetupState, | ||
QuickTransferWizardAction, | ||
} from './types' | ||
|
||
interface SelectDestWellsProps { | ||
onNext: () => void | ||
onBack: () => void | ||
exitButtonProps: React.ComponentProps<typeof SmallButton> | ||
state: QuickTransferSetupState | ||
dispatch: React.Dispatch<QuickTransferWizardAction> | ||
} | ||
|
||
export function SelectDestWells(props: SelectDestWellsProps): JSX.Element { | ||
const { onNext, onBack, exitButtonProps, state, dispatch } = props | ||
const { i18n, t } = useTranslation(['quick_transfer', 'shared']) | ||
|
||
const handleClickNext = (): void => { | ||
// until well selection is implemented, select all wells and proceed to the next step | ||
if (state.destination === 'source' && state.source != null) { | ||
dispatch({ | ||
type: 'SET_DEST_WELLS', | ||
wells: Object.keys(state.source.wells), | ||
}) | ||
} else if (state.destination !== 'source' && state.destination != null) { | ||
dispatch({ | ||
type: 'SET_DEST_WELLS', | ||
wells: Object.keys(state.destination.wells), | ||
}) | ||
} | ||
onNext() | ||
} | ||
return ( | ||
<Flex> | ||
<ChildNavigation | ||
header={t('select_dest_wells')} | ||
onClickBack={onBack} | ||
buttonText={i18n.format(t('shared:continue'), 'capitalize')} | ||
onClickButton={handleClickNext} | ||
buttonIsDisabled={false} | ||
secondaryButtonProps={exitButtonProps} | ||
top={SPACING.spacing8} | ||
/> | ||
<Flex | ||
marginTop={SPACING.spacing120} | ||
padding={`${SPACING.spacing16} ${SPACING.spacing60} ${SPACING.spacing40} ${SPACING.spacing60}`} | ||
> | ||
TODO: Add destination well selection deck map | ||
</Flex> | ||
</Flex> | ||
) | ||
} |
Oops, something went wrong.