Skip to main content

Crafting Directory — DB2 Item Level Sync + Reagent UI Redesign

Notion Task: Crafting Directory — Reagent UI Redesign + DB2 Item Level Sync
Story Points: 8
Epic: Guild Crafting

Overview​

Two-part task:

  • Part A: Backend sync — pull crafting quality item level breakpoints and reagent-item mappings from Wago DB2 CSVs
  • Part B: Frontend UI restructure — merge all reagents into one unified icon-card section (depends on Part A for icon data)

Part A — DB2 Item Level Modifier Sync (Backend)​

Problem​

Crafting quality tiers (Rank 1-5 item levels) are managed via a manual admin table (CraftingQualityTier in Prisma). This data exists authoritatively in Blizzard's DB2 game client tables. Additionally, the ModifiedCraftingReagentItem table provides item-to-slot-type mappings needed by Part B for icon resolution.

DB2 Table Chain​

All available as CSVs from https://wago.tools/db2/{TableName}/csv.

The item level breakpoints for crafting qualities are encoded across 5 linked tables:

1. ModifiedCraftingReagentItem (69 rows)​

ColumnDescription
IDPrimary key
Description_langHuman-readable name (e.g. "Spark of Midnight")
ModifiedCraftingCategoryIDFK → ModifiedCraftingCategory (groups like "Optional Reagents")
ItemBonusTreeIDFK → ItemBonusTree — the key link to item levels
FlagsBitflags
ItemContextOffsetContext offset value

This table also provides the item-to-slot-type mapping needed for Part B icon resolution.

2. ItemBonusTree (2,820 rows)​

ColumnDescription
IDPrimary key
InventoryTypeMaskBitmask for applicable inventory slots

Links to ItemBonusTreeNode via ParentItemBonusTreeID.

3. ItemBonusTreeNode (8,708 rows)​

ColumnDescription
IDPrimary key
ItemContextContext identifier
ChildItemBonusTreeIDRecursive tree link
ChildItemBonusListIDFK → ItemBonusList
ChildItemLevelSelectorIDFK → ItemLevelSelector — this is the goal
ItemBonusListGroupIDFK → ItemBonusListGroup
ParentItemBonusTreeIDFK → ItemBonusTree (parent)

4. ItemLevelSelector (1,148 rows)​

ColumnDescription
IDPrimary key
MinItemLevelBase item level for this selector tier
ItemLevelSelectorQualitySetIDFK → quality offset table

5. ItemLevelSelectorQualitySet (20 rows)​

ColumnDescription
IDPrimary key
IlvlRareItem level offset for rare-quality crafts
IlvlEpicItem level offset for epic-quality crafts

6. ItemLevelSelectorQuality (32 rows)​

ColumnDescription
IDPrimary key
QualityCraft quality rank (1-5)
QualityItemBonusListIDFK → ItemBonusList (the actual bonus IDs)
ParentILSQualitySetIDFK → ItemLevelSelectorQualitySet

How to derive item levels per quality rank​

ModifiedCraftingReagentItem.ItemBonusTreeID
→ ItemBonusTreeNode (where ParentItemBonusTreeID = that ID)
→ ChildItemLevelSelectorID
→ ItemLevelSelector.MinItemLevel (base ilvl)
→ ItemLevelSelector.ItemLevelSelectorQualitySetID
→ ItemLevelSelectorQualitySet.IlvlRare / IlvlEpic
→ ItemLevelSelectorQuality (Quality 1-5 → bonus list IDs)

Implementation Plan​

1. New GDL migration (019_crafting_item_level_selectors.sql)​

CREATE TABLE IF NOT EXISTS wow_modified_crafting_reagent_item (
id INT PRIMARY KEY,
description TEXT NOT NULL DEFAULT '',
modified_crafting_category_id INT NOT NULL,
item_bonus_tree_id INT NOT NULL,
flags INT NOT NULL DEFAULT 0,
item_context_offset INT NOT NULL DEFAULT 0,
synced_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE TABLE IF NOT EXISTS wow_item_bonus_tree_node (
id INT PRIMARY KEY,
item_context SMALLINT NOT NULL DEFAULT 0,
child_item_bonus_tree_id INT NOT NULL DEFAULT 0,
child_item_bonus_list_id INT NOT NULL DEFAULT 0,
child_item_level_selector_id INT NOT NULL DEFAULT 0,
item_bonus_list_group_id INT NOT NULL DEFAULT 0,
parent_item_bonus_tree_id INT NOT NULL DEFAULT 0,
synced_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE TABLE IF NOT EXISTS wow_item_level_selector (
id INT PRIMARY KEY,
min_item_level SMALLINT NOT NULL,
quality_set_id INT NOT NULL,
synced_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE TABLE IF NOT EXISTS wow_item_level_selector_quality_set (
id INT PRIMARY KEY,
ilvl_rare SMALLINT NOT NULL DEFAULT 0,
ilvl_epic SMALLINT NOT NULL DEFAULT 0,
synced_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE TABLE IF NOT EXISTS wow_item_level_selector_quality (
id INT PRIMARY KEY,
quality SMALLINT NOT NULL,
quality_item_bonus_list_id INT NOT NULL,
parent_quality_set_id INT NOT NULL,
synced_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_bonus_tree_node_parent
ON wow_item_bonus_tree_node(parent_item_bonus_tree_id);
CREATE INDEX IF NOT EXISTS idx_bonus_tree_node_ilvl_selector
ON wow_item_bonus_tree_node(child_item_level_selector_id) WHERE child_item_level_selector_id > 0;
CREATE INDEX IF NOT EXISTS idx_ilvl_selector_quality_set
ON wow_item_level_selector(quality_set_id);
CREATE INDEX IF NOT EXISTS idx_ilvl_selector_quality_parent
ON wow_item_level_selector_quality(parent_quality_set_id);

2. New sync function (crafting_item_levels.rs)​

  • Download 5 CSVs: ModifiedCraftingReagentItem, ItemBonusTreeNode, ItemLevelSelector, ItemLevelSelectorQualitySet, ItemLevelSelectorQuality
  • Parse and bulk upsert into the new tables
  • Follow the pattern in crafting_slots.rs (fetch_csv, parse_csv_line helpers)
  • Register as wow.crafting_item_levels data category
  • Wire into adapter.rs, job.rs, sync_service.rs

3. Query function for recipe item level tiers​

Given a recipe's modified_crafting_slots:

SELECT
ils.min_item_level,
ilsqs.ilvl_rare,
ilsqs.ilvl_epic,
ilsq.quality
FROM wow_modified_crafting_reagent_item mcri
JOIN wow_item_bonus_tree_node ibtn
ON ibtn.parent_item_bonus_tree_id = mcri.item_bonus_tree_id
AND ibtn.child_item_level_selector_id > 0
JOIN wow_item_level_selector ils
ON ils.id = ibtn.child_item_level_selector_id
JOIN wow_item_level_selector_quality_set ilsqs
ON ilsqs.id = ils.quality_set_id
JOIN wow_item_level_selector_quality ilsq
ON ilsq.parent_quality_set_id = ilsqs.id
WHERE mcri.id = $1 -- slot type / reagent item ID
ORDER BY ilsq.quality;

4. Update recipe detail API​

  • Include quality tier item levels derived from DB2 data in RecipeDetailDto
  • Fall back to admin CraftingQualityTier table if DB2 data not synced
  • Structure: qualityTiers: [{ rank: 1, itemLevel: 623 }, { rank: 2, itemLevel: 626 }, ...]

5. Admin sync button​

  • Add "Crafting Item Levels" button to admin panel
  • RTK Query mutations, WebSocket hook, progress component, i18n keys (7 locales)
  • Same pattern as the Crafting Slots button

6. Deprecation path for manual CraftingQualityTier​

  • Once DB2 sync is reliable, the admin table becomes fallback/override only
  • Keep the admin UI but mark as "override" — DB2 values take precedence unless manually overridden
  • This avoids needing to manually update numbers each season

Part B — Reagent UI Redesign (Frontend)​

Depends on Part A — needs ModifiedCraftingReagentItem data for icon resolution.

Problem​

The current recipe detail view splits reagents into three separate visual groups:

  1. Provided Reagents — shown as small Chip components (e.g. "Alchemy Combined Reagent x4")
  2. Required Reagents — shown as cards with icons, name, and quantity (e.g. Mote of Primal Energy x6)
  3. Finishing Reagents — shown as Chips

This split reflects the crafting order interface (crafter vs requester-provided), but this page is a directory/lookup view, not the actual crafting UI. Users just want to see "what does this recipe need?" All material reagents should be unified.

Reference Screenshot​

Haranir Preserving Agents: "Provided Reagents" as green/yellow Chips vs "Required Reagents" as icon cards. These should be merged.

Required Changes​

1. Merge all material reagents into a single "Reagents" section​

  • Combine detail.craftingOrderSlots where reagentType === REAGENT_TYPE_PROVIDED (type 1) with detail.reagents into one flat list.
  • Remove the separate "Provided Reagents" and "Required Reagents" headings.
  • Use a single heading: "Reagents" (t('crafting.reagentsTitle')).

2. Unify the visual layout — all reagents as icon cards​

  • Currently provided reagents render as HeroUI Chip components (no icons, just text).
  • Required reagents render as cards with icon, name, and quantity.
  • ALL material reagents should use the card layout: icon on left, name in middle, quantity on right.
  • The card layout is already implemented for required reagents (lines ~756-790 in CraftingDirectoryPage.tsx). Extend this pattern to provided slots.

3. Resolve icon data for provided reagent slots​

CraftingOrderSlot currently has:

interface CraftingOrderSlot {
slotTypeId: number;
slotTypeName: string;
reagentType: number;
reagentCount: number;
reCraftCount: number;
displayOrder: number;
}

It does not have an item icon URL. The slot type names (e.g. "Alchemy Combined Reagent") correspond to item names in wow_items.

Backend change needed in profession_recipe_queries.rs (GDL):

  • When building crafting_order_slots, join against wow_items to resolve an icon_url for each slot.
  • Use the ModifiedCraftingReagentItem table from Part A to map slot types to item IDs.

API/Frontend changes:

  • Update CraftingOrderSlotDto in game-data.service.ts to include iconUrl: string | null.
  • Update frontend CraftingOrderSlot interface in gameDataApi.ts to include iconUrl.

4. Keep finishing reagents / modifiers as a separate subsection​

Finishing reagents (concentration, etc.) and modifier slots (Spark of Midnight, etc.) are NOT recipe ingredients — they're optional enhancements the crafter applies.

  • Keep these in a secondary subsection below the unified reagents, labeled "Crafting Modifiers" or "Optional Enhancements".
  • These can remain as Chips or become small cards — implementer's choice.
  • Modifier types: REAGENT_TYPE_FINISHING (2), modifiers (0), REAGENT_TYPE_SOCKET (3).

5. Wrap provided reagent cards with ItemPopover (tooltips)​

  • Required reagents already have ItemPopover tooltips.
  • Provided reagents should also get tooltips if item data is available.
  • Requires icon resolution from step 3 (need the item ID to fetch preview_item data).

Files to modify​

FileChange
CraftingDirectoryPage.tsxMerge reagent sections, unify card layout
profession_recipe_queries.rsAdd icon URL + item ID to crafting_order_slots query
game-data.service.tsUpdate DTO mapping for new fields
gameDataApi.tsUpdate CraftingOrderSlot interface

Acceptance Criteria​

Part A​

  • New GDL migration creates 5 tables for the bonus tree chain
  • Sync function downloads and parses 5 Wago DB2 CSVs
  • Admin panel has "Crafting Item Levels" sync button with progress
  • Recipe detail API returns quality-tier item levels from DB2 data
  • Fallback to admin CraftingQualityTier table if DB2 data unavailable

Part B​

  • All material reagents (required + provided) appear in a single "Reagents" section
  • All reagents use the same card layout: icon, name, quantity
  • Provided reagent slots show item icons (resolved from wow_items)
  • Finishing reagents / modifiers appear in a separate "Crafting Modifiers" subsection
  • ItemPopover tooltips work on provided reagent cards

Estimated Breakdown​

Sub-taskPoints
Part A: GDL migration + sync function3
Part A: Admin button plumbing1
Part A: GDL query enrichment2
Part B: Frontend UI restructure2