Redesign pick lists for reuse

This commit is contained in:
beatz174-bit
2025-11-21 18:49:35 +10:00
parent 7f24948317
commit 858c1559d7
4 changed files with 163 additions and 24 deletions
+9 -10
View File
@@ -1,6 +1,6 @@
import { Button, Container, Stack, Typography } from '@mui/material';
import { useParams, useNavigate, Link as RouterLink } from 'react-router-dom';
import { useEffect, useMemo } from 'react';
import { useMemo } from 'react';
import { useAreas, usePickItems, usePickList, useProducts } from '../hooks/dataHooks';
import { useDatabase } from '../context/DBProvider';
import { PickItemRow } from '../components/PickItemRow';
@@ -14,10 +14,6 @@ export const ActivePickListScreen = () => {
const db = useDatabase();
const navigate = useNavigate();
useEffect(() => {
if (!id || !pickList) return;
}, [id, pickList]);
const areaName = useMemo(
() => areas.find((area) => area.id === pickList?.area_id)?.name ?? 'Area',
[areas, pickList?.area_id],
@@ -49,9 +45,7 @@ export const ActivePickListScreen = () => {
await db.pickItems.delete(itemId);
};
const completeList = async () => {
if (!id) return;
await db.pickLists.update(id, { completed_at: Date.now() });
const returnToLists = () => {
navigate('/pick-lists');
};
@@ -63,6 +57,11 @@ export const ActivePickListScreen = () => {
Add Item
</Button>
</Stack>
{pickList?.notes ? (
<Typography variant="body2" color="text.secondary" mb={2}>
{pickList.notes}
</Typography>
) : null}
<Stack spacing={1}>
{items.map((item) => (
<PickItemRow
@@ -76,8 +75,8 @@ export const ActivePickListScreen = () => {
/>
))}
</Stack>
<Button fullWidth sx={{ mt: 3 }} variant="outlined" onClick={completeList}>
Complete List
<Button fullWidth sx={{ mt: 3 }} variant="outlined" onClick={returnToLists}>
Save and Return
</Button>
</Container>
);
+2 -2
View File
@@ -8,10 +8,10 @@ export const HomeScreen = () => (
</Typography>
<Stack spacing={2}>
<Button component={RouterLink} to="/start" variant="contained">
Start New Pick List
Create Pick List
</Button>
<Button component={RouterLink} to="/pick-lists" variant="outlined">
View Pick Lists
View & Edit Pick Lists
</Button>
<Button component={RouterLink} to="/products" variant="outlined">
Manage Products
+129 -5
View File
@@ -1,32 +1,156 @@
import { Button, Container, List, ListItemButton, ListItemText, Typography } from '@mui/material';
import {
Button,
Container,
Dialog,
DialogActions,
DialogContent,
DialogTitle,
IconButton,
List,
ListItem,
ListItemButton,
ListItemText,
MenuItem,
Stack,
TextField,
Typography,
} from '@mui/material';
import { Delete, Edit } from '@mui/icons-material';
import { format } from 'date-fns';
import { useMemo, useState } from 'react';
import { Link as RouterLink } from 'react-router-dom';
import { usePickLists, useAreas } from '../hooks/dataHooks';
import { useDatabase } from '../context/DBProvider';
import { PickList } from '../models/PickList';
export const PickListsScreen = () => {
const lists = usePickLists();
const areas = useAreas();
const db = useDatabase();
const [editingList, setEditingList] = useState<PickList | null>(null);
const [areaId, setAreaId] = useState('');
const [notes, setNotes] = useState('');
const sortedLists = useMemo(() => {
return [...lists].sort((a, b) => a.created_at - b.created_at);
}, [lists]);
const getAreaName = (areaId: string) => areas.find((a) => a.id === areaId)?.name ?? 'Unknown area';
const openEdit = (list: PickList) => {
setEditingList(list);
setAreaId(list.area_id);
setNotes(list.notes ?? '');
};
const closeEdit = () => {
setEditingList(null);
setAreaId('');
setNotes('');
};
const saveEdit = async () => {
if (!editingList || !areaId) return;
await db.pickLists.update(editingList.id, {
area_id: areaId,
notes: notes.trim() || undefined,
});
closeEdit();
};
const deleteList = async (list: PickList) => {
const confirmed = window.confirm('Remove this pick list and its items?');
if (!confirmed) return;
await db.pickItems.where('pick_list_id').equals(list.id).delete();
await db.pickLists.delete(list.id);
};
return (
<Container sx={{ py: 4 }}>
<Typography variant="h5" gutterBottom>
Pick Lists
</Typography>
<Button component={RouterLink} to="/start" variant="contained" sx={{ mb: 2 }}>
Start New
Add Pick List
</Button>
<List>
{lists.map((list) => (
<ListItemButton key={list.id} component={RouterLink} to={`/pick-lists/${list.id}`} divider>
{sortedLists.map((list) => (
<ListItem key={list.id} divider secondaryAction={
<Stack direction="row" spacing={1}>
<IconButton
edge="end"
aria-label="Edit"
onClick={(event) => {
event.stopPropagation();
event.preventDefault();
openEdit(list);
}}
>
<Edit />
</IconButton>
<IconButton
edge="end"
aria-label="Delete"
onClick={(event) => {
event.stopPropagation();
event.preventDefault();
deleteList(list);
}}
>
<Delete />
</IconButton>
</Stack>
}>
<ListItemButton component={RouterLink} to={`/pick-lists/${list.id}`}>
<ListItemText
primary={getAreaName(list.area_id)}
secondary={format(list.created_at, 'PPpp')}
secondary={
<Stack spacing={0.5}>
{list.notes ? <span>{list.notes}</span> : null}
<Typography variant="caption" color="text.secondary">
Created {format(list.created_at, 'PPpp')}
</Typography>
</Stack>
}
/>
</ListItemButton>
</ListItem>
))}
</List>
<Dialog open={Boolean(editingList)} onClose={closeEdit} fullWidth>
<DialogTitle>Edit Pick List</DialogTitle>
<DialogContent sx={{ pt: 1 }}>
<Stack spacing={2} mt={1}>
<TextField
select
fullWidth
label="Area"
value={areaId}
onChange={(event) => setAreaId(event.target.value)}
>
{areas.map((area) => (
<MenuItem key={area.id} value={area.id}>
{area.name}
</MenuItem>
))}
</TextField>
<TextField
label="Notes"
value={notes}
onChange={(event) => setNotes(event.target.value)}
multiline
minRows={2}
/>
</Stack>
</DialogContent>
<DialogActions>
<Button onClick={closeEdit}>Cancel</Button>
<Button variant="contained" onClick={saveEdit} disabled={!areaId}>
Save Changes
</Button>
</DialogActions>
</Dialog>
</Container>
);
};
+19 -3
View File
@@ -10,18 +10,27 @@ export const StartPickListScreen = () => {
const db = useDatabase();
const navigate = useNavigate();
const [areaId, setAreaId] = useState('');
const [notes, setNotes] = useState('');
const start = async () => {
if (!areaId) return;
const pickListId = uuidv4();
await db.pickLists.add({ id: pickListId, area_id: areaId, created_at: Date.now() });
await db.pickLists.add({
id: pickListId,
area_id: areaId,
created_at: Date.now(),
notes: notes.trim() || undefined,
});
navigate(`/pick-lists/${pickListId}`);
};
return (
<Container sx={{ py: 4 }}>
<Typography variant="h5" gutterBottom>
Start Pick List
Create Pick List
</Typography>
<Typography variant="body2" color="text.secondary" gutterBottom>
Pick lists are reusable. Create one for each store area and update it anytime you restock.
</Typography>
<Stack spacing={2}>
<TextField
@@ -37,8 +46,15 @@ export const StartPickListScreen = () => {
</MenuItem>
))}
</TextField>
<TextField
label="Notes (optional)"
value={notes}
onChange={(event) => setNotes(event.target.value)}
multiline
minRows={2}
/>
<Button variant="contained" disabled={!areaId} onClick={start}>
Start
Save Pick List
</Button>
</Stack>
</Container>