Deduplicate prefilled pick list products
This commit is contained in:
1 parent
1efa5a161d
commit
b9ca6f7e31
3 files changed
+278
-21
No files matched your search
@@ -1,25 +1,98 @@
|
||||
import { Button, Container, MenuItem, Stack, TextField, Typography } from '@mui/material';
|
||||
import { useState } from 'react';
|
||||
import {
|
||||
Button,
|
||||
Checkbox,
|
||||
Container,
|
||||
FormControlLabel,
|
||||
FormGroup,
|
||||
MenuItem,
|
||||
Stack,
|
||||
TextField,
|
||||
Typography,
|
||||
} from '@mui/material';
|
||||
import { useMemo, useState } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { useAreas } from '../hooks/dataHooks';
|
||||
import { useAreas, useCategories } from '../hooks/dataHooks';
|
||||
import { useDatabase } from '../context/DBProvider';
|
||||
|
||||
export const StartPickListScreen = () => {
|
||||
const areas = useAreas();
|
||||
const categories = useCategories();
|
||||
const db = useDatabase();
|
||||
const navigate = useNavigate();
|
||||
const [areaId, setAreaId] = useState('');
|
||||
const [notes, setNotes] = useState('');
|
||||
const [selectedCategories, setSelectedCategories] = useState<string[]>([]);
|
||||
|
||||
const sortedCategories = useMemo(
|
||||
() =>
|
||||
[...categories].sort((a, b) =>
|
||||
a.name.localeCompare(b.name, undefined, { sensitivity: 'base' }),
|
||||
),
|
||||
[categories],
|
||||
);
|
||||
|
||||
const handleToggleCategory = (categoryId: string) => {
|
||||
setSelectedCategories((current) =>
|
||||
current.includes(categoryId)
|
||||
? current.filter((id) => id !== categoryId)
|
||||
: [...current, categoryId],
|
||||
);
|
||||
};
|
||||
|
||||
const start = async () => {
|
||||
if (!areaId) return;
|
||||
const pickListId = uuidv4();
|
||||
await db.pickLists.add({
|
||||
id: pickListId,
|
||||
area_id: areaId,
|
||||
created_at: Date.now(),
|
||||
notes: notes.trim() || undefined,
|
||||
const timestamp = Date.now();
|
||||
|
||||
const selectedCategoryNames = categories
|
||||
.filter((category) => selectedCategories.includes(category.id))
|
||||
.map((category) => category.name);
|
||||
|
||||
await db.transaction('rw', db.pickLists, db.pickItems, db.products, async () => {
|
||||
await db.pickLists.add({
|
||||
id: pickListId,
|
||||
area_id: areaId,
|
||||
created_at: timestamp,
|
||||
notes: notes.trim() || undefined,
|
||||
});
|
||||
|
||||
if (selectedCategoryNames.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const products = await db.products.toArray();
|
||||
const productsInCategories = products.filter(
|
||||
(product) => selectedCategoryNames.includes(product.category) && !product.archived,
|
||||
);
|
||||
|
||||
const uniqueProducts: typeof productsInCategories = [];
|
||||
const seenNames = new Set<string>();
|
||||
|
||||
productsInCategories.forEach((product) => {
|
||||
const nameKey = product.name.toLowerCase();
|
||||
if (!seenNames.has(nameKey)) {
|
||||
seenNames.add(nameKey);
|
||||
uniqueProducts.push(product);
|
||||
}
|
||||
});
|
||||
|
||||
if (productsInCategories.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
await db.pickItems.bulkAdd(
|
||||
uniqueProducts.map((product) => ({
|
||||
id: uuidv4(),
|
||||
pick_list_id: pickListId,
|
||||
product_id: product.id,
|
||||
quantity: 1,
|
||||
is_carton: false,
|
||||
status: 'pending',
|
||||
created_at: timestamp,
|
||||
updated_at: timestamp,
|
||||
})),
|
||||
);
|
||||
});
|
||||
navigate(`/pick-lists/${pickListId}`);
|
||||
};
|
||||
@@ -47,12 +120,30 @@ export const StartPickListScreen = () => {
|
||||
))}
|
||||
</TextField>
|
||||
<TextField
|
||||
fullWidth
|
||||
label="Notes (optional)"
|
||||
value={notes}
|
||||
onChange={(event) => setNotes(event.target.value)}
|
||||
multiline
|
||||
minRows={2}
|
||||
/>
|
||||
<Stack spacing={1}>
|
||||
<Typography variant="subtitle2">Add categories to prefill products</Typography>
|
||||
<FormGroup>
|
||||
{sortedCategories.map((category) => (
|
||||
<FormControlLabel
|
||||
key={category.id}
|
||||
control={
|
||||
<Checkbox
|
||||
checked={selectedCategories.includes(category.id)}
|
||||
onChange={() => handleToggleCategory(category.id)}
|
||||
/>
|
||||
}
|
||||
label={category.name}
|
||||
/>
|
||||
))}
|
||||
</FormGroup>
|
||||
</Stack>
|
||||
<Button variant="contained" disabled={!areaId} onClick={start}>
|
||||
Save Pick List
|
||||
</Button>
|
||||
|
||||
Reference in new issue
Block a user