Skip to content

UX: Category delete — no product warning, orphaned products, missing frontend role checks #64

Description

@khaira777

Problem

Two issues with category deletion:

1. No warning about products under the category

When deleting a category, the confirmation dialog just says "Delete this category?" — no indication of how many products will be orphaned.

2. Products become orphaned

Categories are soft-deleted (deleted_at set), but products referencing that category keep their category_id pointing to the deleted category. There is no ON DELETE clause on the foreign key. Products are not deleted, moved, or reassigned — they become invisible in the category hierarchy but still exist in the database.

3. No frontend role checks

Edit and delete buttons on the Products page are shown to all users regardless of role. The backend requires owner/manager role, but cashiers/waiters see the buttons and get a generic "Failed to delete" error (403).

Proposed Fix

1. Warn about products before delete

In the backend DELETE /categories/:id route, count products under the category before soft-deleting and return the count:

const productCount = db.prepare(
  'SELECT COUNT(*) as count FROM products WHERE category_id = ? AND deleted_at IS NULL'
).get(req.params.id).count;

if (productCount > 0) {
  return res.status(400).json({
    error: `Cannot delete category with ${productCount} product(s). Reassign or delete products first.`,
    productCount
  });
}

Or, if soft-delete-with-orphaning is intentional, show the count in the frontend confirmation:

const confirmMsg = productCount > 0
  ? `Delete this category? ${productCount} product(s) will lose their category.`
  : 'Delete this category?';

2. Frontend role checks

Hide edit/delete buttons for non-owner/manager users:

const isOwnerOrManager = currentTenant?.role === 'owner' || currentTenant?.role === 'manager';

// Only show edit/delete for authorized users
{isOwnerOrManager && (
  <>
    <button onClick={() => openEditCategory(cat)}>...</button>
    <button onClick={() => handleCategoryDelete(cat.id)}>...</button>
  </>
)}

Apply the same pattern to product and addon group delete buttons.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    Fields

    No fields configured for Bug.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions