diff --git a/src/screens/ManageAreasScreen.test.tsx b/src/screens/ManageAreasScreen.test.tsx
new file mode 100644
index 0000000..d9689d1
--- /dev/null
+++ b/src/screens/ManageAreasScreen.test.tsx
@@ -0,0 +1,51 @@
+import { MemoryRouter } from 'react-router-dom';
+import { render, screen } from '@testing-library/react';
+import userEvent from '@testing-library/user-event';
+import { describe, expect, it, vi } from 'vitest';
+import { ManageAreasScreen } from './ManageAreasScreen';
+
+const areasMock = [{ id: 'area-1', name: 'Front Counter', created_at: 0, updated_at: 0 }];
+
+vi.mock('../hooks/dataHooks', () => ({
+ useAreas: () => areasMock,
+}));
+
+const areaDeleteMock = vi.fn();
+const pickListCountMock = vi.fn();
+
+vi.mock('../context/DBProvider', () => ({
+ useDatabase: () => ({
+ areas: {
+ add: vi.fn(),
+ update: vi.fn(),
+ delete: areaDeleteMock,
+ },
+ pickLists: {
+ where: () => ({
+ equals: () => ({
+ count: pickListCountMock,
+ }),
+ }),
+ },
+ }),
+}));
+
+describe('ManageAreasScreen deletion safeguards', () => {
+ it('prevents deleting an area that is used by pick lists', async () => {
+ pickListCountMock.mockResolvedValueOnce(1);
+
+ const user = userEvent.setup();
+ render(
+
+
+ ,
+ );
+
+ await user.click(screen.getByRole('button', { name: /delete front counter/i }));
+
+ expect(areaDeleteMock).not.toHaveBeenCalled();
+ expect(
+ await screen.findByText(/cannot delete this area while 1 pick list\(s\) use it/i),
+ ).toBeVisible();
+ });
+});
diff --git a/src/screens/ManageAreasScreen.tsx b/src/screens/ManageAreasScreen.tsx
index 61cd5db..d84e4d8 100644
--- a/src/screens/ManageAreasScreen.tsx
+++ b/src/screens/ManageAreasScreen.tsx
@@ -1,4 +1,6 @@
import {
+ Alert,
+ AlertColor,
Button,
Container,
IconButton,
@@ -24,6 +26,7 @@ export const ManageAreasScreen = () => {
const [name, setName] = useState('');
const [editingAreaId, setEditingAreaId] = useState(null);
const [editName, setEditName] = useState('');
+ const [feedback, setFeedback] = useState<{ text: string; severity: AlertColor } | null>(null);
const addArea = async () => {
if (!name) return;
@@ -34,6 +37,7 @@ export const ManageAreasScreen = () => {
const startEditing = (areaId: string, currentName: string) => {
setEditingAreaId(areaId);
setEditName(currentName);
+ setFeedback(null);
};
const saveArea = async () => {
@@ -41,6 +45,7 @@ export const ManageAreasScreen = () => {
await db.areas.update(editingAreaId, { name: editName, updated_at: Date.now() });
setEditingAreaId(null);
setEditName('');
+ setFeedback({ text: 'Area updated.', severity: 'success' });
};
const cancelEditing = () => {
@@ -49,10 +54,19 @@ export const ManageAreasScreen = () => {
};
const deleteArea = async (areaId: string) => {
+ const usageCount = await db.pickLists.where('area_id').equals(areaId).count();
+ if (usageCount > 0) {
+ setFeedback({
+ text: `Cannot delete this area while ${usageCount} pick list(s) use it. Remove those lists first.`,
+ severity: 'error',
+ });
+ return;
+ }
await db.areas.delete(areaId);
if (editingAreaId === areaId) {
cancelEditing();
}
+ setFeedback({ text: 'Area deleted.', severity: 'success' });
};
return (
@@ -61,6 +75,7 @@ export const ManageAreasScreen = () => {
Manage Areas
+ {feedback ? {feedback.text} : null}
setName(event.target.value)} />