Merge branch 'main' into codex/investigate-mobile-deletion-flow-and-test-fixes
This commit is contained in:
@@ -42,8 +42,32 @@ const baseProduct: Product = {
|
||||
};
|
||||
|
||||
describe('PickItemRow', () => {
|
||||
beforeEach(() => {
|
||||
mockMatchMedia(false);
|
||||
it('keeps quantity inline with matching typography to the product name', () => {
|
||||
render(
|
||||
<PickItemRow
|
||||
item={baseItem}
|
||||
product={baseProduct}
|
||||
onIncrementQuantity={vi.fn()}
|
||||
onDecrementQuantity={vi.fn()}
|
||||
onToggleCarton={vi.fn()}
|
||||
onStatusChange={vi.fn()}
|
||||
onDelete={vi.fn()}
|
||||
/>,
|
||||
);
|
||||
|
||||
const productName = screen.getByText(baseProduct.name);
|
||||
const quantityLabel = screen.getByText('1 unit');
|
||||
const titleRow = screen.getByTestId('pick-item-title-row');
|
||||
|
||||
const rowStyle = getComputedStyle(titleRow);
|
||||
expect(rowStyle.display).toBe('flex');
|
||||
expect(rowStyle.flexDirection).toBe('row');
|
||||
|
||||
const productStyle = getComputedStyle(productName);
|
||||
const quantityStyle = getComputedStyle(quantityLabel);
|
||||
|
||||
expect(productStyle.fontSize).toBe(quantityStyle.fontSize);
|
||||
expect(productStyle.fontWeight).toBe(quantityStyle.fontWeight);
|
||||
});
|
||||
|
||||
it('asks for confirmation before deleting a product from the pick list', async () => {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Add, Close, Delete, Inventory2, Remove } from '@mui/icons-material';
|
||||
import { Add, Close, Delete, Inventory2, MoreHoriz, Remove } from '@mui/icons-material';
|
||||
import {
|
||||
Button,
|
||||
Checkbox,
|
||||
@@ -16,7 +16,7 @@ import { alpha, useTheme } from '@mui/material/styles';
|
||||
import type React from 'react';
|
||||
import { useState } from 'react';
|
||||
import { PickItem } from '../models/PickItem';
|
||||
import { Product } from '../models/Product';
|
||||
import { DEFAULT_BULK_NAME, DEFAULT_UNIT_TYPE, Product } from '../models/Product';
|
||||
|
||||
interface PickItemRowProps {
|
||||
item: PickItem;
|
||||
@@ -42,8 +42,8 @@ export const PickItemRow = ({
|
||||
const [isControlsOpen, setIsControlsOpen] = useState(false);
|
||||
const isNarrowScreen = useMediaQuery(theme.breakpoints.down('sm'));
|
||||
const packagingLabel = item.is_carton
|
||||
? product?.bulk_name ?? 'Carton'
|
||||
: product?.unit_type ?? 'Unit';
|
||||
? product?.bulk_name ?? DEFAULT_BULK_NAME
|
||||
: product?.unit_type ?? DEFAULT_UNIT_TYPE;
|
||||
|
||||
const toggleStatus = (checked: boolean) => {
|
||||
onStatusChange(checked ? 'picked' : 'pending');
|
||||
@@ -65,6 +65,10 @@ export const PickItemRow = ({
|
||||
}
|
||||
};
|
||||
|
||||
const handleCloseControls = () => {
|
||||
setIsControlsOpen(false);
|
||||
};
|
||||
|
||||
const handleRowKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {
|
||||
if (!isNarrowScreen) return;
|
||||
|
||||
@@ -85,7 +89,7 @@ export const PickItemRow = ({
|
||||
justifyContent="space-between"
|
||||
spacing={1.5}
|
||||
sx={{
|
||||
p: 1,
|
||||
p: 1.5,
|
||||
borderRadius: 1,
|
||||
bgcolor: 'background.paper',
|
||||
boxShadow: 1,
|
||||
@@ -102,30 +106,32 @@ export const PickItemRow = ({
|
||||
checked={item.status === 'picked'}
|
||||
onChange={(event) => toggleStatus(event.target.checked)}
|
||||
inputProps={{ 'aria-label': 'Toggle picked status' }}
|
||||
onClick={(event) => event.stopPropagation()}
|
||||
/>
|
||||
<Stack spacing={0.5} minWidth={0} flex={1}>
|
||||
<Typography
|
||||
variant="subtitle1"
|
||||
noWrap
|
||||
sx={{ display: 'flex', alignItems: 'center', gap: 1 }}
|
||||
<Stack
|
||||
direction="row"
|
||||
spacing={1}
|
||||
alignItems="center"
|
||||
data-testid="pick-item-title-row"
|
||||
sx={{ minWidth: 0 }}
|
||||
>
|
||||
<Typography
|
||||
component="span"
|
||||
variant="subtitle1"
|
||||
noWrap
|
||||
sx={{ minWidth: 0, overflow: 'hidden', textOverflow: 'ellipsis' }}
|
||||
sx={{ minWidth: 0, overflow: 'hidden', textOverflow: 'ellipsis', fontWeight: 600 }}
|
||||
>
|
||||
{product?.name ?? 'Unknown product'}
|
||||
</Typography>
|
||||
<Typography
|
||||
component="span"
|
||||
variant="subtitle1"
|
||||
sx={{ fontWeight: 700, whiteSpace: 'nowrap' }}
|
||||
noWrap
|
||||
sx={{ fontWeight: 600, whiteSpace: 'nowrap' }}
|
||||
>
|
||||
{item.quantity} {packagingLabel}
|
||||
</Typography>
|
||||
</Typography>
|
||||
</Stack>
|
||||
{isNarrowScreen && (
|
||||
<Typography variant="caption" color="text.secondary" noWrap>
|
||||
Tap to adjust quantity and packaging
|
||||
@@ -133,6 +139,40 @@ export const PickItemRow = ({
|
||||
)}
|
||||
</Stack>
|
||||
</Stack>
|
||||
{isDesktop ? (
|
||||
<Stack direction="row" spacing={0.5} alignItems="center" flexWrap="wrap" justifyContent="flex-end">
|
||||
<IconButton
|
||||
aria-label={`Switch to ${item.is_carton ? 'unit' : 'carton'} packaging`}
|
||||
color={item.is_carton ? 'primary' : 'default'}
|
||||
onClick={onToggleCarton}
|
||||
sx={{
|
||||
boxShadow: item.is_carton
|
||||
? (theme) => `0 0 0 8px ${alpha(theme.palette.primary.main, 0.15)}`
|
||||
: 'none',
|
||||
}}
|
||||
>
|
||||
<Inventory2 />
|
||||
</IconButton>
|
||||
<IconButton aria-label="Decrease quantity" color="primary" onClick={onDecrementQuantity}>
|
||||
<Remove />
|
||||
</IconButton>
|
||||
<IconButton aria-label="Increase quantity" color="primary" onClick={onIncrementQuantity}>
|
||||
<Add />
|
||||
</IconButton>
|
||||
<IconButton
|
||||
color="error"
|
||||
onClick={() => setIsConfirmOpen(true)}
|
||||
aria-label="Delete item"
|
||||
sx={{ ml: { xs: 0, sm: 1 } }}
|
||||
>
|
||||
<Delete />
|
||||
</IconButton>
|
||||
</Stack>
|
||||
) : (
|
||||
<IconButton aria-label="Open item controls" onClick={openControls}>
|
||||
<MoreHoriz />
|
||||
</IconButton>
|
||||
)}
|
||||
|
||||
{!isNarrowScreen && (
|
||||
<Stack direction="row" spacing={1} alignItems="center">
|
||||
@@ -187,7 +227,7 @@ export const PickItemRow = ({
|
||||
{isNarrowScreen && (
|
||||
<Dialog
|
||||
open={isControlsOpen}
|
||||
onClose={() => setIsControlsOpen(false)}
|
||||
onClose={handleCloseControls}
|
||||
fullWidth
|
||||
maxWidth="xs"
|
||||
aria-labelledby="item-controls-title"
|
||||
@@ -201,10 +241,7 @@ export const PickItemRow = ({
|
||||
</Typography>
|
||||
<IconButton
|
||||
aria-label="Close controls"
|
||||
onClick={(event) => {
|
||||
stopPropagation(event);
|
||||
setIsControlsOpen(false);
|
||||
}}
|
||||
onClick={handleCloseControls}
|
||||
>
|
||||
<Close />
|
||||
</IconButton>
|
||||
|
||||
Reference in New Issue
Block a user