Restructure project to root layout
This commit is contained in:
1 parent
e0e26a34ab
commit
3ffe9bbf99
51 files changed
+16
-12
No files matched your search
@@ -0,0 +1,27 @@
|
||||
import { Alert, Card, CardContent, Typography } from '@mui/material';
|
||||
import { useBarcodeScanner } from '../hooks/useBarcodeScanner';
|
||||
|
||||
interface BarcodeScannerViewProps {
|
||||
onDetected?: (code: string) => void;
|
||||
}
|
||||
|
||||
export const BarcodeScannerView = ({ onDetected }: BarcodeScannerViewProps) => {
|
||||
const { videoRef, result } = useBarcodeScanner();
|
||||
|
||||
if (result.code && onDetected) {
|
||||
onDetected(result.code);
|
||||
}
|
||||
|
||||
return (
|
||||
<Card variant="outlined">
|
||||
<CardContent>
|
||||
<Typography variant="subtitle1" gutterBottom>
|
||||
Scan Barcode
|
||||
</Typography>
|
||||
<video ref={videoRef} style={{ width: '100%', borderRadius: 8 }} />
|
||||
{result.code ? <Alert severity="success">Detected {result.code}</Alert> : null}
|
||||
{result.error ? <Alert severity="error">{result.error}</Alert> : null}
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,20 @@
|
||||
import { Button, ButtonProps } from '@mui/material';
|
||||
import React from 'react';
|
||||
import { useLongPress } from '../hooks/useLongPress';
|
||||
|
||||
interface LongPressButtonProps extends ButtonProps {
|
||||
onLongPress: () => void;
|
||||
}
|
||||
|
||||
export const LongPressButton = ({ onLongPress, onClick, children, ...rest }: LongPressButtonProps) => {
|
||||
const gestureHandlers = useLongPress({
|
||||
onLongPress,
|
||||
onClick: onClick ? () => onClick({} as React.MouseEvent<HTMLButtonElement>) : undefined,
|
||||
});
|
||||
|
||||
return (
|
||||
<Button {...rest} {...gestureHandlers} onClick={undefined}>
|
||||
{children}
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,34 @@
|
||||
import { IconButton, Stack, TextField } from '@mui/material';
|
||||
import RemoveIcon from '@mui/icons-material/Remove';
|
||||
import AddIcon from '@mui/icons-material/Add';
|
||||
|
||||
interface NumericStepperProps {
|
||||
label?: string;
|
||||
value: number;
|
||||
onChange: (value: number) => void;
|
||||
min?: number;
|
||||
}
|
||||
|
||||
export const NumericStepper = ({ label, value, onChange, min = 0 }: NumericStepperProps) => (
|
||||
<Stack direction="row" alignItems="center" spacing={1}>
|
||||
<IconButton
|
||||
aria-label={`decrease ${label ?? 'value'}`}
|
||||
onClick={() => onChange(Math.max(min, value - 1))}
|
||||
size="small"
|
||||
>
|
||||
<RemoveIcon />
|
||||
</IconButton>
|
||||
<TextField
|
||||
size="small"
|
||||
type="number"
|
||||
label={label}
|
||||
value={value}
|
||||
onChange={(event) => onChange(Number(event.target.value))}
|
||||
inputProps={{ min }}
|
||||
sx={{ width: 120 }}
|
||||
/>
|
||||
<IconButton aria-label={`increase ${label ?? 'value'}`} onClick={() => onChange(value + 1)} size="small">
|
||||
<AddIcon />
|
||||
</IconButton>
|
||||
</Stack>
|
||||
);
|
||||
@@ -0,0 +1,52 @@
|
||||
import { Chip, Stack, Typography } from '@mui/material';
|
||||
import { PickItem, PickItemStatus } from '../models/PickItem';
|
||||
import { Product } from '../models/Product';
|
||||
import { useLongPress } from '../hooks/useLongPress';
|
||||
import { useSwipe } from '../hooks/useSwipe';
|
||||
|
||||
interface PickItemRowProps {
|
||||
item: PickItem;
|
||||
product?: Product | null;
|
||||
onIncrementUnit: () => void;
|
||||
onIncrementBulk: () => void;
|
||||
onSwipeLeft: () => void;
|
||||
onSwipeRight: () => void;
|
||||
}
|
||||
|
||||
const statusColor: Record<PickItemStatus, 'default' | 'success' | 'warning'> = {
|
||||
pending: 'default',
|
||||
picked: 'success',
|
||||
skipped: 'warning',
|
||||
};
|
||||
|
||||
export const PickItemRow = ({
|
||||
item,
|
||||
product,
|
||||
onIncrementUnit,
|
||||
onIncrementBulk,
|
||||
onSwipeLeft,
|
||||
onSwipeRight,
|
||||
}: PickItemRowProps) => {
|
||||
const longPressHandlers = useLongPress({ onLongPress: onIncrementBulk, onClick: onIncrementUnit });
|
||||
const swipeHandlers = useSwipe({ onSwipeLeft, onSwipeRight });
|
||||
|
||||
return (
|
||||
<Stack
|
||||
direction="row"
|
||||
alignItems="center"
|
||||
justifyContent="space-between"
|
||||
spacing={1}
|
||||
sx={{ p: 1, borderRadius: 1, bgcolor: 'background.paper', boxShadow: 1 }}
|
||||
{...longPressHandlers}
|
||||
{...swipeHandlers}
|
||||
>
|
||||
<div>
|
||||
<Typography variant="subtitle1">{product?.name ?? 'Unknown product'}</Typography>
|
||||
<Typography variant="caption" color="text.secondary">
|
||||
{item.quantity_units} units / {item.quantity_bulk} bulk
|
||||
</Typography>
|
||||
</div>
|
||||
<Chip label={item.status} color={statusColor[item.status]} size="small" />
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,26 @@
|
||||
import { Card, CardContent, Stack, Typography } from '@mui/material';
|
||||
import { Product } from '../models/Product';
|
||||
|
||||
interface ProductRowProps {
|
||||
product: Product;
|
||||
}
|
||||
|
||||
export const ProductRow = ({ product }: ProductRowProps) => (
|
||||
<Card variant="outlined" sx={{ mb: 1 }}>
|
||||
<CardContent>
|
||||
<Stack direction="row" justifyContent="space-between" alignItems="center">
|
||||
<div>
|
||||
<Typography variant="subtitle1">{product.name}</Typography>
|
||||
<Typography variant="caption" color="text.secondary">
|
||||
{product.category} • {product.unit_type}
|
||||
</Typography>
|
||||
</div>
|
||||
{product.bulk_name && product.units_per_bulk ? (
|
||||
<Typography variant="caption" color="text.secondary">
|
||||
{product.units_per_bulk} per {product.bulk_name}
|
||||
</Typography>
|
||||
) : null}
|
||||
</Stack>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
@@ -0,0 +1,18 @@
|
||||
import { Box, Paper } from '@mui/material';
|
||||
import { PropsWithChildren } from 'react';
|
||||
import { useSwipe } from '../hooks/useSwipe';
|
||||
|
||||
interface SwipeableRowProps extends PropsWithChildren {
|
||||
onSwipeLeft?: () => void;
|
||||
onSwipeRight?: () => void;
|
||||
}
|
||||
|
||||
export const SwipeableRow = ({ children, onSwipeLeft, onSwipeRight }: SwipeableRowProps) => {
|
||||
const gestureHandlers = useSwipe({ onSwipeLeft, onSwipeRight });
|
||||
|
||||
return (
|
||||
<Paper sx={{ p: 1, mb: 1 }} {...gestureHandlers}>
|
||||
<Box>{children}</Box>
|
||||
</Paper>
|
||||
);
|
||||
};
|
||||
Reference in new issue
Block a user