Inventory Flow¶
This page explains how the inventory feature works end-to-end: screens, components, hooks, and the Supabase tables they touch.
Screens & key components¶
Inventory screen (/inventory, /inventory/new, /inventory/edit/:id)¶
File: src/pages/Inventory.tsx
Responsibilities:
- List and manage all inventory items for the current company/tenant.
- Support separate views for Active vs Archived items.
- Provide search, filter, sort, and low-stock highlighting.
- Handle creating, editing, duplicating, archiving, and unarchiving items.
Key pieces:
-
Tabs (Active / Archived)
- Backed by a boolean flag passed to
fetchInventoryItems(isActive). archiveInventoryItems(ids)andunarchiveInventoryItems(ids)toggle archival state in bulk.
- Backed by a boolean flag passed to
-
Search and filters
filters.searchfilters items by:- SKU
- Product name
- Description
- Category
- Price-like values (if search string is numeric, matches against retail/wholesale/cost as strings).
filters.stockLevelsupports:out_of_stock– stock = 0.low_stock– stock > 0 and ≤low_stock_threshold.in_stock– stock >low_stock_threshold.filters.sortBycontrols sorting by name, SKU, price, wholesale price, cost, or available stock.
-
Low stock badge
- Uses
getLowStockItems()from the inventory hook. - Displays a Low Stock button with a
Badgeshowing the count. - Clicking toggles the low-stock filter.
- Uses
-
Inventory table
- File:
src/components/inventory/InventoryTable.tsx - Displays items with columns for SKU, product name, category, pricing, and stock.
- Supports row selection for bulk archive/unarchive.
- Integrates sorting callbacks (
onSort) and selection state.
- File:
-
Inventory form
- File:
src/components/inventory/InventoryForm.tsx - Used for both create and update flows.
- Receives
itemandonSubmitprops (wired tocreateInventoryItem/updateInventoryItem). - Handles core fields: SKU, name, category, description, prices, stock, stock thresholds, vendor, etc.
- File:
-
Product edit modal
- File:
src/components/inventory/ProductEditModal.tsx - Used when clicking a row or variation.
- Loads full item (via
fetchInventoryItem) including variations. - Allows editing variations, photos, and advanced settings while viewing context.
- File:
-
Keyboard shortcuts
Ctrl+N– open create item form.Ctrl+F– focus search input.
Hooks & operations¶
Inventory hooks are organized via a facade:
File: src/hooks/useInventory.ts
- Combines domain-specific hooks:
useInventoryShared– shared loading/error state.useInventoryItems– CRUD for items.useInventoryPhotos– photos for items.useVariationAttributes/useVariationAttributeValues– attribute definitions and values.useProductVariations– variant rows.useVariationPhotos– variant-level photos.
The combined interface exposes:
-
Items
fetchInventoryItems(isActive: boolean)– fetch list of items (active vs archived).fetchInventoryItem(id)– fetch a single item with details/variations.createInventoryItem(input)– create new item.updateInventoryItem(input)– update existing item.deleteInventoryItem(id)– hard-delete item.getLowStockItems()– used for low-stock badge.archiveInventoryItems(ids)/unarchiveInventoryItems(ids)– bulk archive toggles.
-
Variations & attributes
- CRUD for variation attributes and values.
createProductVariation,updateProductVariation,deleteProductVariation,bulkCreateProductVariations,bulkUpdateProductVariations.
-
Photos
uploadInventoryPhoto,deleteInventoryPhoto,setPrimaryPhoto.uploadVariationPhoto,assignPhotoToVariation,deleteVariationPhoto,setVariationPrimaryPhoto,reorderVariationPhotos.
These hooks ultimately call Supabase via shared utilities in integrations/supabase.
Tables touched¶
The exact schema is defined in migrations, but the key tables are:
-
inventory_items- Core product metadata for each SKUs.
- Fields (from migrations and type usage):
id– primary key.tenant_id/company_id– multi-tenant isolation.sku,product_name,category,subcategory.item_description.retail_price,wholesale_price,cost_of_goods.current_stock_qty– stock-level for base product.track_quantity– whether stock should be decremented.low_stock_threshold– used for low-stock checks.track_variant_inventory– whether stock is derived from variants.- Archive flag / timestamps (e.g.
archived_at).
-
Variant-related tables (names inferred from migrations and hooks):
product_variations– per-variant rows linked toinventory_items.variation_attributes– defines variation dimensions (e.g. size, color).variation_attribute_values– possible values per attribute.variation_photos– mapping photos to specific variants.
-
Payment-related tables
pay_link_line_itemsreferencesinventory_items(id)for pay links:
order_line_items.item_nameis populated from inventory product names for invoices and order displays.
Authoritative schemas
For exact column definitions and relationships, see the Supabase migrations referenced in Supabase Architecture and the API/Data → Supabase Tables page.
CRUD & behavior¶
Create¶
- Triggered via Create Item button on the inventory screen.
- Opens
InventoryFormwith noitem. - On submit:
- Calls
createInventoryItem(input). - Refreshes inventory list via
loadItems(). - If route was
/inventory/new, navigates to/inventory/edit/:idfor the new item.
- Calls
Read¶
- List view uses
fetchInventoryItems(isActive).- Filtered and sorted in
Inventory.tsxbased onfilters.
- Filtered and sorted in
- Detail view uses
fetchInventoryItem(id)when:- Navigating to
/inventory/edit/:id. - Opening the
ProductEditModalfrom a row click.
- Navigating to
Update¶
- Editing base item:
- If
editingItemis set,InventoryFormcallsupdateInventoryItem({ id, ...data }).
- If
- Editing variations:
ProductEditModalcallsupdateInventoryItem(itemId, data)and variation-specific hooks.- Variations can be added, updated, or removed via the variation-specific hooks.
- Updating photos:
- Uses
uploadInventoryPhoto/uploadVariationPhotoand related helpers.
- Uses
Delete¶
- Deleting items:
deleteInventoryItem(id)from row actions.- After deletion, reloads inventory and low-stock count.
- Deleting variations:
deleteProductVariation(variationId)and then reloads inventory and low-stock count.
Archive / Unarchive¶
- Archive flow:
- User selects rows and clicks Archive.
archiveInventoryItems(Array.from(selectedItems))is called.- On success, selection is cleared and inventory reloaded.
- Unarchive flow:
- Same pattern via
unarchiveInventoryItemsfrom the Archived tab.
- Same pattern via
- Archived items:
- Hidden from main selection lists.
- Still referenced in historical orders, invoices, and pay links.
Search & filter behavior¶
Search logic in Inventory.tsx:
- Treats
filters.searchas a free-text query. - Matches against:
- Base fields:
sku,product_name,item_description,category. - Prices (if the search string is numeric).
- Variation fields:
- Combined SKU:
item.sku + variation.sku_suffix. - Variation
display_name. - Joined attribute values (e.g. size/color combinations).
- Base fields:
Stock-level filter:
- Uses computed stock per item:
- If
track_variant_inventoryistrueand item has variations: - Stock = sum of all
variation.current_stock_qtyvalues. - Otherwise: stock =
current_stock_qty.
- If
- Interprets
low_stock_thresholdper item.
Sorting:
filters.sortByvalues map to UI columns:alphabetical→ product name.sku_asc/sku_desc→ SKU.price_asc/price_desc→ min/max retail price (considering variations).wholesale_price_*,cost_*→ min/max values including variations.stock_*→ computed stock per item.
Flow diagram¶
flowchart LR
U[User] --> INV[/Inventory screen/]
INV --> HOOK[useInventory hook]
HOOK --> DB[(Supabase: inventory_items & variations)]
INV --> FILTERS[Search & filters]
FILTERS --> INV
click INV "../architecture/frontend/" "Inventory page and components"
click HOOK "../architecture/frontend/" "Frontend hooks & data fetching"
click DB "../architecture/supabase/" "Supabase schema (inventory tables)"
Narrative:
- User navigates to
/inventoryand sees the Inventory screen. - The screen calls
useInventoryto fetch items from Supabase. - The result set is filtered and sorted client-side by search, stock level, and sort options.
- CRUD operations call back into
useInventoryhooks, which in turn persist changes to Supabase. - Related flows (orders, pay links, payments) reference inventory items by
inventory_item_idanditem_name.
Related docs¶
- Supabase Architecture – for inventory-related tables and RLS.
- Frontend Architecture – for route map and providers.
- Flows → Orders – for how inventory items are linked to orders.
- Flows → Payments – for pay links and invoice line items referencing inventory.