HASH 5cf89dc714a9
DATE 2025-07-28
SUBJECT web: profile css
FILES 4 CHANGED
HASH 5cf89dc714a9
DATE 2025-07-28
SUBJECT web: profile css
FILES 4 CHANGED
┌─ web/src/components/ItemDatabase.astro ────────────────────────────────────┐
│ diff --git a/web/src/components/ItemDatabase.astro b/web/src/components/ItemDataba │
│ se.astro │
│ index 37de99f..79364d2 100644 │
│ --- a/web/src/components/ItemDatabase.astro │
│ +++ b/web/src/components/ItemDatabase.astro │
│ @@ -102,53 +102,49 @@ window.ItemDatabase = { │
│ const wowheadUrl = window.ItemDatabase.getWowheadUrl(item.id); │
│ const iconUrl = item.icon ? `https://wow.zamimg.com/images/wow/icons/large/${ │
│ item.icon}.jpg` : null; │
│ │
│ - // Build details array from enriched data │
│ + // Build details array with specific layout structure │
│ const details = []; │
│ │
│ - // Item stats from scalingOptions │
│ - if (item.stats) { │
│ - const stats = []; │
│ - if (item.stats.ilvl) stats.push(`Item Level: ${item.stats.ilvl}`); │
│ - if (item.stats.weaponDamageMin && item.stats.weaponDamageMax) { │
│ - stats.push(`Damage: ${item.stats.weaponDamageMin}-${item.stats.weaponDama │
│ geMax}`); │
│ - } │
│ - if (stats.length > 0) details.push(...stats); │
│ + // Item Level (white text) │
│ + if (item.stats && item.stats.ilvl) { │
│ + details.push(`<div class="item-level">Item Level ${item.stats.ilvl}</div>`) │
│ ; │
│ } │
│ │
│ - // Enriched reforging information │
│ + // Slot (determine from item type - this might need enhancement) │
│ + // For now, we'll skip slot since it's shown in the header already │
│ + │
│ + // Reforged (green text) │
│ if (item.reforging && item.reforging.description) { │
│ - details.push(`Reforge: ${item.reforging.description}`); │
│ + details.push(`<div class="item-reforge">Reforged ${item.reforging.descripti │
│ on}</div>`); │
│ } else if (item.reforging && typeof item.reforging === 'number') { │
│ // Fallback to manual reforge lookup if not enriched │
│ const reforge = reforgeData[item.reforging.toString()]; │
│ if (reforge) { │
│ const fromStat = statNames[reforge.s1] || reforge.s1; │
│ const toStat = statNames[reforge.s2] || reforge.s2; │
│ - details.push(`Reforge: ${fromStat} ? ${toStat}`); │
│ + details.push(`<div class="item-reforge">Reforged ${fromStat} ? ${toStat}< │
│ /div>`); │
│ } │
│ } │
│ │
│ - // Enriched gems information │
│ + // Gems - each gem on separate line with icon and white stats │
│ if (item.gems && item.gems.length > 0) { │
│ item.gems.forEach(gem => { │
│ - if (gem && gem.description) { │
│ - // Use enriched gem description (includes name and stats) │
│ - details.push(gem.description); │
│ - } else if (gem && gem.name) { │
│ - // Use enriched gem name if available │
│ - details.push(gem.name); │
│ + if (gem && gem.name) { │
│ + const gemIcon = gem.icon ? `<img src="https://wow.zamimg.com/images/wow │
│ /icons/small/${gem.icon}.jpg" alt="${gem.name}" class="gem-icon-inline" />` : ''; │
│ + const gemStats = gem.stats && gem.stats.length > 0 ? gem.stats.join(', │
│ ') : gem.name; │
│ + details.push(`<div class="gem-line">${gemIcon}<span class="gem-stats-wh │
│ ite">${gemStats}</span></div>`); │
│ } else if (gem && typeof gem === 'number') { │
│ // Fallback for non-enriched gem IDs │
│ - details.push(`Gem ${gem}`); │
│ + details.push(`<div class="gem-line">Gem ${gem}</div>`); │
│ } │
│ }); │
│ } │
│ │
│ - // Enriched enchant information │
│ + // Enchant (green text) │
│ if (item.enchant && item.enchant.name) { │
│ - details.push(`Enchant: ${item.enchant.name}`); │
│ + details.push(`<div class="item-enchant">${item.enchant.name}</div>`); │
│ } else if (item.enchant && typeof item.enchant === 'number') { │
│ - details.push(`Enchant ${item.enchant}`); │
│ + details.push(`<div class="item-enchant">Enchant ${item.enchant}</div>`); │
│ } │
│ │
│ // Tinker (not enriched yet, but prepared for future) │
└────────────────────────────────────────────────────────────────────────────────────┘
┌─ ...components/ItemDatabase.astro ───┐
│ diff --git a/web/src/components/ItemDatabase │
│ .astro b/web/src/components/ItemDatabase.ast │
│ ro │
│ index 37de99f..79364d2 100644 │
│ --- a/web/src/components/ItemDatabase.astro │
│ +++ b/web/src/components/ItemDatabase.astro │
│ @@ -102,53 +102,49 @@ window.ItemDatabase = │
│ { │
│ const wowheadUrl = window.ItemDatabase. │
│ getWowheadUrl(item.id); │
│ const iconUrl = item.icon ? `https://wo │
│ w.zamimg.com/images/wow/icons/large/${item.i │
│ con}.jpg` : null; │
│ │
│ - // Build details array from enriched da │
│ ta │
│ + // Build details array with specific la │
│ yout structure │
│ const details = []; │
│ │
│ - // Item stats from scalingOptions │
│ - if (item.stats) { │
│ - const stats = []; │
│ - if (item.stats.ilvl) stats.push(`Item │
│ Level: ${item.stats.ilvl}`); │
│ - if (item.stats.weaponDamageMin && ite │
│ m.stats.weaponDamageMax) { │
│ - stats.push(`Damage: ${item.stats.we │
│ aponDamageMin}-${item.stats.weaponDamageMax} │
│ `); │
│ - } │
│ - if (stats.length > 0) details.push(.. │
│ .stats); │
│ + // Item Level (white text) │
│ + if (item.stats && item.stats.ilvl) { │
│ + details.push(`<div class="item-level" │
│ >Item Level ${item.stats.ilvl}</div>`); │
│ } │
│ │
│ - // Enriched reforging information │
│ + // Slot (determine from item type - thi │
│ s might need enhancement) │
│ + // For now, we'll skip slot since it's │
│ shown in the header already │
│ + │
│ + // Reforged (green text) │
│ if (item.reforging && item.reforging.de │
│ scription) { │
│ - details.push(`Reforge: ${item.reforgi │
│ ng.description}`); │
│ + details.push(`<div class="item-reforg │
│ e">Reforged ${item.reforging.description}</d │
│ iv>`); │
│ } else if (item.reforging && typeof ite │
│ m.reforging === 'number') { │
│ // Fallback to manual reforge lookup │
│ if not enriched │
│ const reforge = reforgeData[item.refo │
│ rging.toString()]; │
│ if (reforge) { │
│ const fromStat = statNames[reforge. │
│ s1] || reforge.s1; │
│ const toStat = statNames[reforge.s2 │
│ ] || reforge.s2; │
│ - details.push(`Reforge: ${fromStat} │
│ ? ${toStat}`); │
│ + details.push(`<div class="item-refo │
│ rge">Reforged ${fromStat} ? ${toStat}</div>` │
│ ); │
│ } │
│ } │
│ │
│ - // Enriched gems information │
│ + // Gems - each gem on separate line wit │
│ h icon and white stats │
│ if (item.gems && item.gems.length > 0) │
│ { │
│ item.gems.forEach(gem => { │
│ - if (gem && gem.description) { │
│ - // Use enriched gem description ( │
│ includes name and stats) │
│ - details.push(gem.description); │
│ - } else if (gem && gem.name) { │
│ - // Use enriched gem name if avail │
│ able │
│ - details.push(gem.name); │
│ + if (gem && gem.name) { │
│ + const gemIcon = gem.icon ? `<img │
│ src="https://wow.zamimg.com/images/wow/icons │
│ /small/${gem.icon}.jpg" alt="${gem.name}" cl │
│ ass="gem-icon-inline" />` : ''; │
│ + const gemStats = gem.stats && gem │
│ .stats.length > 0 ? gem.stats.join(', ') : g │
│ em.name; │
│ + details.push(`<div class="gem-lin │
│ e">${gemIcon}<span class="gem-stats-white">$ │
│ {gemStats}</span></div>`); │
│ } else if (gem && typeof gem === 'n │
│ umber') { │
│ // Fallback for non-enriched gem │
│ IDs │
│ - details.push(`Gem ${gem}`); │
│ + details.push(`<div class="gem-lin │
│ e">Gem ${gem}</div>`); │
│ } │
│ }); │
│ } │
│ │
│ - // Enriched enchant information │
│ + // Enchant (green text) │
│ if (item.enchant && item.enchant.name) │
│ { │
│ - details.push(`Enchant: ${item.enchant │
│ .name}`); │
│ + details.push(`<div class="item-enchan │
│ t">${item.enchant.name}</div>`); │
│ } else if (item.enchant && typeof item. │
│ enchant === 'number') { │
│ - details.push(`Enchant ${item.enchant} │
│ `); │
│ + details.push(`<div class="item-enchan │
│ t">Enchant ${item.enchant}</div>`); │
│ } │
│ │
│ // Tinker (not enriched yet, but prepar │
│ ed for future) │
└──────────────────────────────────────────────┘
┌─ web/src/components/ItemTooltip.astro ─────────────────────────────────────┐
│ diff --git a/web/src/components/ItemTooltip.astro b/web/src/components/ItemTooltip │
│ .astro │
│ new file mode 100644 │
│ index 0000000..c5715c1 │
│ --- /dev/null │
│ +++ b/web/src/components/ItemTooltip.astro │
│ @@ -0,0 +1,312 @@ │
│ +--- │
│ +interface Props { │
│ + item: { │
│ + name: string; │
│ + icon?: string; │
│ + quality?: number; │
│ + stats?: { │
│ + ilvl?: number; │
│ + stats?: { [key: string]: number }; │
│ + }; │
│ + type?: number; │
│ + gems?: Array<{ │
│ + name: string; │
│ + icon?: string; │
│ + stats?: string[]; │
│ + quality?: number; │
│ + }>; │
│ + enchant?: { │
│ + name: string; │
│ + }; │
│ + reforging?: { │
│ + description: string; │
│ + }; │
│ + }; │
│ +} │
│ + │
│ +const { item } = Astro.props; │
│ + │
│ +// Slot type mappings (based on WoW equipment slot types) │
│ +const slotNames: { [key: number]: string } = { │
│ + 1: "Head", │
│ + 2: "Neck", │
│ + 3: "Shoulder", │
│ + 4: "Shirt", │
│ + 5: "Chest", │
│ + 6: "Waist", │
│ + 7: "Legs", │
│ + 8: "Feet", │
│ + 9: "Wrists", │
│ + 10: "Hands", │
│ + 11: "Ring", │
│ + 12: "Trinket", │
│ + 13: "One-Hand", │
│ + 14: "Shield", │
│ + 15: "Ranged", │
│ + 16: "Back", │
│ + 17: "Two-Hand", │
│ + 18: "Bag", │
│ + 19: "Tabard", │
│ + 20: "Robe", │
│ + 21: "Main Hand", │
│ + 22: "Off Hand", │
│ + 23: "Held In Off-hand", │
│ + 24: "Ammo", │
│ + 25: "Thrown", │
│ + 26: "Ranged Right", │
│ + 28: "Relic" │
│ +}; │
│ + │
│ +// Stat name mappings (from itemDatabase.nix) │
│ +const statNames: { [key: string]: string } = { │
│ + "0": "Strength", │
│ + "1": "Agility", │
│ + "2": "Stamina", │
│ + "3": "Intellect", │
│ + "4": "Spirit", │
│ + "5": "Hit Rating", │
│ + "6": "Crit Rating", │
│ + "7": "Haste Rating", │
│ + "8": "Expertise Rating", │
│ + "9": "Dodge Rating", │
│ + "10": "Parry Rating", │
│ + "11": "Mastery Rating", │
│ + "17": "Armor" │
│ +}; │
│ + │
│ +// Quality color classes │
│ +const qualityColors: { [key: number]: string } = { │
│ + 0: "quality-0", // Poor (Gray) │
│ + 1: "quality-1", // Common (White) │
│ + 2: "quality-2", // Uncommon (Green) │
│ + 3: "quality-3", // Rare (Blue) │
│ + 4: "quality-4", // Epic (Purple) │
│ + 5: "quality-5", // Legendary (Orange) │
│ + 6: "quality-6", // Artifact (Light Red) │
│ + 7: "quality-7" // Heirloom (Gold) │
│ +}; │
│ + │
│ +const slotName = item.type ? slotNames[item.type] || "Unknown" : ""; │
│ +const qualityClass = item.quality !== undefined ? qualityColors[item.quality] || │
│ "" : ""; │
│ + │
│ +// Parse item stats │
│ +const itemStats: string[] = []; │
│ +let armorValue = 0; │
│ + │
│ +if (item.stats?.stats) { │
│ + Object.entries(item.stats.stats).forEach(([statId, value]) => { │
│ + if (value > 0) { │
│ + if (statId === "17") { │
│ + armorValue = value; // Armor │
│ + } else { │
│ + const statName = statNames[statId]; │
│ + if (statName) { │
│ + itemStats.push(`+${value} ${statName}`); │
│ + } │
│ + } │
│ + } │
│ + }); │
│ +} │
│ +--- │
│ + │
│ +<div class="item-tooltip"> │
│ + <div class={`item-name ${qualityClass}`}> │
│ + {item.name} │
│ + </div> │
│ + │
│ + {item.stats?.ilvl && ( │
│ + <div class="item-ilvl"> │
│ + ilvl: {item.stats.ilvl} │
│ + </div> │
│ + )} │
│ + │
│ + {slotName && ( │
│ + <div class="item-slot"> │
│ + {slotName} │
│ + </div> │
│ + )} │
│ + │
│ + {armorValue > 0 && ( │
│ + <div class="item-armor"> │
│ + {armorValue} Armor │
│ + </div> │
│ + )} │
│ + │
│ + {itemStats.length > 0 && ( │
│ + <div class="item-stats"> │
│ + {itemStats.map(stat => ( │
│ + <div class="item-stat">{stat}</div> │
│ + ))} │
│ + </div> │
│ + )} │
│ + │
│ + {item.enchant && ( │
│ + <div class="item-enchant"> │
│ + Enchanted: {item.enchant.name} │
│ + </div> │
│ + )} │
│ + │
│ + {item.reforging && ( │
│ + <div class="item-reforge"> │
│ + Reforged: {item.reforging.description} │
│ + </div> │
│ + )} │
│ + │
│ + {item.gems && item.gems.length > 0 && ( │
│ + <div class="item-gems"> │
│ + <div class="gems-title">Gems:</div> │
│ + {item.gems.map(gem => ( │
│ + <div class="gem-item"> │
│ + {gem.icon && ( │
│ + <img │
│ + src={`https://wow.zamimg.com/images/wow/icons/small/${gem.icon}.jpg │
│ `} │
│ + alt={gem.name} │
│ + class="gem-icon" │
│ + loading="lazy" │
│ + /> │
│ + )} │
│ + <div class="gem-info"> │
│ + <div class={`gem-name ${gem.quality !== undefined ? qualityColors[gem │
│ .quality] : ''}`}> │
│ + {gem.name} │
│ + </div> │
│ + {gem.stats && gem.stats.length > 0 && ( │
│ + <div class="gem-stats"> │
│ + {gem.stats.map(stat => ( │
│ + <div class="gem-stat">{stat}</div> │
│ + ))} │
│ + </div> │
│ + )} │
│ + </div> │
│ + </div> │
│ + ))} │
│ + </div> │
│ + )} │
│ +</div> │
│ + │
│ +<style> │
│ + .item-tooltip { │
│ + background: linear-gradient(135deg, #1a1a1a 0%, #2a2a2a 100%); │
│ + border: 2px solid #444; │
│ + border-radius: 8px; │
│ + padding: 12px; │
│ + color: #fff; │
│ + font-family: 'Segoe UI', Arial, sans-serif; │
│ + font-size: 13px; │
│ + line-height: 1.4; │
│ + min-width: 200px; │
│ + max-width: 300px; │
│ + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.8); │
│ + position: relative; │
│ + } │
│ + │
│ + .item-tooltip::before { │
│ + content: ''; │
│ + position: absolute; │
│ + top: 0; │
│ + left: 0; │
│ + right: 0; │
│ + height: 1px; │
│ + background: linear-gradient(90deg, transparent, #666, transparent); │
│ + } │
│ + │
│ + .item-name { │
│ + font-weight: bold; │
│ + font-size: 14px; │
│ + margin-bottom: 4px; │
│ + text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.8); │
│ + } │
│ + │
│ + .item-ilvl { │
│ + color: #ffd700; │
│ + font-weight: 500; │
│ + margin-bottom: 2px; │
│ + } │
│ + │
│ + .item-slot { │
│ + color: #aaa; │
│ + font-style: italic; │
│ + margin-bottom: 6px; │
│ + } │
│ + │
│ + .item-armor { │
│ + color: #c0c0c0; │
│ + margin-bottom: 6px; │
│ + font-weight: 500; │
│ + } │
│ + │
│ + .item-stats { │
│ + margin-bottom: 8px; │
│ + } │
│ + │
│ + .item-stat { │
│ + color: #40ff40; │
│ + font-weight: 500; │
│ + margin-bottom: 1px; │
│ + } │
│ + │
│ + .item-enchant { │
│ + color: #40ff40; │
│ + font-style: italic; │
│ + margin-bottom: 4px; │
│ + } │
│ + │
│ + .item-reforge { │
│ + color: #ff8040; │
│ + font-style: italic; │
│ + margin-bottom: 8px; │
│ + } │
│ + │
│ + .item-gems { │
│ + border-top: 1px solid #444; │
│ + padding-top: 8px; │
│ + } │
│ + │
│ + .gems-title { │
│ + color: #ffd700; │
│ + font-weight: 600; │
│ + margin-bottom: 6px; │
│ + } │
│ + │
│ + .gem-item { │
│ + display: flex; │
│ + align-items: flex-start; │
│ + gap: 6px; │
│ + margin-bottom: 4px; │
│ + } │
│ + │
│ + .gem-icon { │
│ + width: 16px; │
│ + height: 16px; │
│ + border-radius: 2px; │
│ + flex-shrink: 0; │
│ + } │
│ + │
│ + .gem-info { │
│ + flex: 1; │
│ + } │
│ + │
│ + .gem-name { │
│ + font-weight: 500; │
│ + margin-bottom: 1px; │
│ + font-size: 12px; │
│ + } │
│ + │
│ + .gem-stats { │
│ + font-size: 11px; │
│ + } │
│ + │
│ + .gem-stat { │
│ + color: #40ff40; │
│ + margin-bottom: 1px; │
│ + } │
│ + │
│ + /* Quality colors - matching WoW item quality */ │
│ + .quality-0 { color: #9d9d9d; } /* Poor (Gray) */ │
│ + .quality-1 { color: #ffffff; } /* Common (White) */ │
│ + .quality-2 { color: #1eff00; } /* Uncommon (Green) */ │
│ + .quality-3 { color: #0070dd; } /* Rare (Blue) */ │
│ + .quality-4 { color: #a335ee; } /* Epic (Purple) */ │
│ + .quality-5 { color: #ff8000; } /* Legendary (Orange) */ │
│ + .quality-6 { color: #e6cc80; } /* Artifact (Light Red) */ │
│ + .quality-7 { color: #00ccff; } /* Heirloom (Gold) */ │
│ +</style> │
│ \ No newline at end of file │
└────────────────────────────────────────────────────────────────────────────────────┘
┌─ .../components/ItemTooltip.astro ───┐
│ diff --git a/web/src/components/ItemTooltip. │
│ astro b/web/src/components/ItemTooltip.astro │
│ new file mode 100644 │
│ index 0000000..c5715c1 │
│ --- /dev/null │
│ +++ b/web/src/components/ItemTooltip.astro │
│ @@ -0,0 +1,312 @@ │
│ +--- │
│ +interface Props { │
│ + item: { │
│ + name: string; │
│ + icon?: string; │
│ + quality?: number; │
│ + stats?: { │
│ + ilvl?: number; │
│ + stats?: { [key: string]: number }; │
│ + }; │
│ + type?: number; │
│ + gems?: Array<{ │
│ + name: string; │
│ + icon?: string; │
│ + stats?: string[]; │
│ + quality?: number; │
│ + }>; │
│ + enchant?: { │
│ + name: string; │
│ + }; │
│ + reforging?: { │
│ + description: string; │
│ + }; │
│ + }; │
│ +} │
│ + │
│ +const { item } = Astro.props; │
│ + │
│ +// Slot type mappings (based on WoW equipme │
│ nt slot types) │
│ +const slotNames: { [key: number]: string } │
│ = { │
│ + 1: "Head", │
│ + 2: "Neck", │
│ + 3: "Shoulder", │
│ + 4: "Shirt", │
│ + 5: "Chest", │
│ + 6: "Waist", │
│ + 7: "Legs", │
│ + 8: "Feet", │
│ + 9: "Wrists", │
│ + 10: "Hands", │
│ + 11: "Ring", │
│ + 12: "Trinket", │
│ + 13: "One-Hand", │
│ + 14: "Shield", │
│ + 15: "Ranged", │
│ + 16: "Back", │
│ + 17: "Two-Hand", │
│ + 18: "Bag", │
│ + 19: "Tabard", │
│ + 20: "Robe", │
│ + 21: "Main Hand", │
│ + 22: "Off Hand", │
│ + 23: "Held In Off-hand", │
│ + 24: "Ammo", │
│ + 25: "Thrown", │
│ + 26: "Ranged Right", │
│ + 28: "Relic" │
│ +}; │
│ + │
│ +// Stat name mappings (from itemDatabase.ni │
│ x) │
│ +const statNames: { [key: string]: string } │
│ = { │
│ + "0": "Strength", │
│ + "1": "Agility", │
│ + "2": "Stamina", │
│ + "3": "Intellect", │
│ + "4": "Spirit", │
│ + "5": "Hit Rating", │
│ + "6": "Crit Rating", │
│ + "7": "Haste Rating", │
│ + "8": "Expertise Rating", │
│ + "9": "Dodge Rating", │
│ + "10": "Parry Rating", │
│ + "11": "Mastery Rating", │
│ + "17": "Armor" │
│ +}; │
│ + │
│ +// Quality color classes │
│ +const qualityColors: { [key: number]: strin │
│ g } = { │
│ + 0: "quality-0", // Poor (Gray) │
│ + 1: "quality-1", // Common (White) │
│ + 2: "quality-2", // Uncommon (Green) │
│ + 3: "quality-3", // Rare (Blue) │
│ + 4: "quality-4", // Epic (Purple) │
│ + 5: "quality-5", // Legendary (Orange) │
│ + 6: "quality-6", // Artifact (Light Red) │
│ + 7: "quality-7" // Heirloom (Gold) │
│ +}; │
│ + │
│ +const slotName = item.type ? slotNames[item │
│ .type] || "Unknown" : ""; │
│ +const qualityClass = item.quality !== undef │
│ ined ? qualityColors[item.quality] || "" : " │
│ "; │
│ + │
│ +// Parse item stats │
│ +const itemStats: string[] = []; │
│ +let armorValue = 0; │
│ + │
│ +if (item.stats?.stats) { │
│ + Object.entries(item.stats.stats).forEach( │
│ ([statId, value]) => { │
│ + if (value > 0) { │
│ + if (statId === "17") { │
│ + armorValue = value; // Armor │
│ + } else { │
│ + const statName = statNames[statId]; │
│ + if (statName) { │
│ + itemStats.push(`+${value} ${statN │
│ ame}`); │
│ + } │
│ + } │
│ + } │
│ + }); │
│ +} │
│ +--- │
│ + │
│ +<div class="item-tooltip"> │
│ + <div class={`item-name ${qualityClass}`}> │
│ + {item.name} │
│ + </div> │
│ + │
│ + {item.stats?.ilvl && ( │
│ + <div class="item-ilvl"> │
│ + ilvl: {item.stats.ilvl} │
│ + </div> │
│ + )} │
│ + │
│ + {slotName && ( │
│ + <div class="item-slot"> │
│ + {slotName} │
│ + </div> │
│ + )} │
│ + │
│ + {armorValue > 0 && ( │
│ + <div class="item-armor"> │
│ + {armorValue} Armor │
│ + </div> │
│ + )} │
│ + │
│ + {itemStats.length > 0 && ( │
│ + <div class="item-stats"> │
│ + {itemStats.map(stat => ( │
│ + <div class="item-stat">{stat}</div> │
│ + ))} │
│ + </div> │
│ + )} │
│ + │
│ + {item.enchant && ( │
│ + <div class="item-enchant"> │
│ + Enchanted: {item.enchant.name} │
│ + </div> │
│ + )} │
│ + │
│ + {item.reforging && ( │
│ + <div class="item-reforge"> │
│ + Reforged: {item.reforging.description │
│ } │
│ + </div> │
│ + )} │
│ + │
│ + {item.gems && item.gems.length > 0 && ( │
│ + <div class="item-gems"> │
│ + <div class="gems-title">Gems:</div> │
│ + {item.gems.map(gem => ( │
│ + <div class="gem-item"> │
│ + {gem.icon && ( │
│ + <img │
│ + src={`https://wow.zamimg.com/ │
│ images/wow/icons/small/${gem.icon}.jpg`} │
│ + alt={gem.name} │
│ + class="gem-icon" │
│ + loading="lazy" │
│ + /> │
│ + )} │
│ + <div class="gem-info"> │
│ + <div class={`gem-name ${gem.qua │
│ lity !== undefined ? qualityColors[gem.quali │
│ ty] : ''}`}> │
│ + {gem.name} │
│ + </div> │
│ + {gem.stats && gem.stats.length │
│ > 0 && ( │
│ + <div class="gem-stats"> │
│ + {gem.stats.map(stat => ( │
│ + <div class="gem-stat">{st │
│ at}</div> │
│ + ))} │
│ + </div> │
│ + )} │
│ + </div> │
│ + </div> │
│ + ))} │
│ + </div> │
│ + )} │
│ +</div> │
│ + │
│ +<style> │
│ + .item-tooltip { │
│ + background: linear-gradient(135deg, #1a │
│ 1a1a 0%, #2a2a2a 100%); │
│ + border: 2px solid #444; │
│ + border-radius: 8px; │
│ + padding: 12px; │
│ + color: #fff; │
│ + font-family: 'Segoe UI', Arial, sans-se │
│ rif; │
│ + font-size: 13px; │
│ + line-height: 1.4; │
│ + min-width: 200px; │
│ + max-width: 300px; │
│ + box-shadow: 0 4px 12px rgba(0, 0, 0, 0. │
│ 8); │
│ + position: relative; │
│ + } │
│ + │
│ + .item-tooltip::before { │
│ + content: ''; │
│ + position: absolute; │
│ + top: 0; │
│ + left: 0; │
│ + right: 0; │
│ + height: 1px; │
│ + background: linear-gradient(90deg, tran │
│ sparent, #666, transparent); │
│ + } │
│ + │
│ + .item-name { │
│ + font-weight: bold; │
│ + font-size: 14px; │
│ + margin-bottom: 4px; │
│ + text-shadow: 1px 1px 2px rgba(0, 0, 0, │
│ 0.8); │
│ + } │
│ + │
│ + .item-ilvl { │
│ + color: #ffd700; │
│ + font-weight: 500; │
│ + margin-bottom: 2px; │
│ + } │
│ + │
│ + .item-slot { │
│ + color: #aaa; │
│ + font-style: italic; │
│ + margin-bottom: 6px; │
│ + } │
│ + │
│ + .item-armor { │
│ + color: #c0c0c0; │
│ + margin-bottom: 6px; │
│ + font-weight: 500; │
│ + } │
│ + │
│ + .item-stats { │
│ + margin-bottom: 8px; │
│ + } │
│ + │
│ + .item-stat { │
│ + color: #40ff40; │
│ + font-weight: 500; │
│ + margin-bottom: 1px; │
│ + } │
│ + │
│ + .item-enchant { │
│ + color: #40ff40; │
│ + font-style: italic; │
│ + margin-bottom: 4px; │
│ + } │
│ + │
│ + .item-reforge { │
│ + color: #ff8040; │
│ + font-style: italic; │
│ + margin-bottom: 8px; │
│ + } │
│ + │
│ + .item-gems { │
│ + border-top: 1px solid #444; │
│ + padding-top: 8px; │
│ + } │
│ + │
│ + .gems-title { │
│ + color: #ffd700; │
│ + font-weight: 600; │
│ + margin-bottom: 6px; │
│ + } │
│ + │
│ + .gem-item { │
│ + display: flex; │
│ + align-items: flex-start; │
│ + gap: 6px; │
│ + margin-bottom: 4px; │
│ + } │
│ + │
│ + .gem-icon { │
│ + width: 16px; │
│ + height: 16px; │
│ + border-radius: 2px; │
│ + flex-shrink: 0; │
│ + } │
│ + │
│ + .gem-info { │
│ + flex: 1; │
│ + } │
│ + │
│ + .gem-name { │
│ + font-weight: 500; │
│ + margin-bottom: 1px; │
│ + font-size: 12px; │
│ + } │
│ + │
│ + .gem-stats { │
│ + font-size: 11px; │
│ + } │
│ + │
│ + .gem-stat { │
│ + color: #40ff40; │
│ + margin-bottom: 1px; │
│ + } │
│ + │
│ + /* Quality colors - matching WoW item qua │
│ lity */ │
│ + .quality-0 { color: #9d9d9d; } /* Poor (G │
│ ray) */ │
│ + .quality-1 { color: #ffffff; } /* Common │
│ (White) */ │
│ + .quality-2 { color: #1eff00; } /* Uncommo │
│ n (Green) */ │
│ + .quality-3 { color: #0070dd; } /* Rare (B │
│ lue) */ │
│ + .quality-4 { color: #a335ee; } /* Epic (P │
│ urple) */ │
│ + .quality-5 { color: #ff8000; } /* Legenda │
│ ry (Orange) */ │
│ + .quality-6 { color: #e6cc80; } /* Artifac │
│ t (Light Red) */ │
│ + .quality-7 { color: #00ccff; } /* Heirloo │
│ m (Gold) */ │
│ +</style> │
│ \ No newline at end of file │
└──────────────────────────────────────────────┘
┌─ web/src/components/Navigation.astro ──────────────────────────────────────┐
│ diff --git a/web/src/components/Navigation.astro b/web/src/components/Navigation.a │
│ stro │
│ index 03da033..e6f378c 100644 │
│ --- a/web/src/components/Navigation.astro │
│ +++ b/web/src/components/Navigation.astro │
│ @@ -16,7 +16,7 @@ │
│ <a href="/" class="navbar-link">Rankings</a> │
│ <a href="/comparison" class="navbar-link">Comparisons</a> │
│ <a href="/faq" class="navbar-link">FAQ</a> │
│ - <a href="https://wowsims.com/mop" class="navbar-link" target="_blank" rel=" │
│ noopener noreferrer">WoWsims</a> │
│ + <a href="https://wowsims.com/mop" class="navbar-link" target="_blank" rel=" │
│ noopener noreferrer">WoWSims</a> │
│ <a href="https://github.com/ooks-io/wowsim-stats" class="navbar-link navbar │
│ -link-github" target="_blank" rel="noopener noreferrer"> │
│ <svg class="github-icon" viewBox="0 0 24 24" fill="currentColor" xmlns="h │
│ ttp://www.w3.org/2000/svg"> │
│ <path d="M12 0C5.374 0 0 5.373 0 12 0 17.302 3.438 21.8 8.207 23.387c.5 │
│ 99.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.33 │
│ 3-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 │
│ 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1. │
│ 334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1 │
│ .008-.322 3.301 1.23A11.509 11.509 0 0112 5.803c1.02.005 2.047.138 3.006.404 2.291 │
│ -1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 │
│ 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192 │
│ .694.801.576C20.566 21.797 24 17.300 24 12c0-6.627-5.373-12-12-12z"/> │
└────────────────────────────────────────────────────────────────────────────────────┘
┌─ ...c/components/Navigation.astro ───┐
│ diff --git a/web/src/components/Navigation.a │
│ stro b/web/src/components/Navigation.astro │
│ index 03da033..e6f378c 100644 │
│ --- a/web/src/components/Navigation.astro │
│ +++ b/web/src/components/Navigation.astro │
│ @@ -16,7 +16,7 @@ │
│ <a href="/" class="navbar-link">Ranki │
│ ngs</a> │
│ <a href="/comparison" class="navbar-l │
│ ink">Comparisons</a> │
│ <a href="/faq" class="navbar-link">FA │
│ Q</a> │
│ - <a href="https://wowsims.com/mop" cla │
│ ss="navbar-link" target="_blank" rel="noopen │
│ er noreferrer">WoWsims</a> │
│ + <a href="https://wowsims.com/mop" cla │
│ ss="navbar-link" target="_blank" rel="noopen │
│ er noreferrer">WoWSims</a> │
│ <a href="https://github.com/ooks-io/w │
│ owsim-stats" class="navbar-link navbar-link- │
│ github" target="_blank" rel="noopener norefe │
│ rrer"> │
│ <svg class="github-icon" viewBox="0 │
│ 0 24 24" fill="currentColor" xmlns="http:// │
│ www.w3.org/2000/svg"> │
│ <path d="M12 0C5.374 0 0 5.373 0 │
│ 12 0 17.302 3.438 21.8 8.207 23.387c.599.111 │
│ .793-.261.793-.577v-2.234c-3.338.726-4.033-1 │
│ .416-4.033-1.416-.546-1.387-1.333-1.756-1.33 │
│ 3-1.756-1.089-.745.083-.729.083-.729 1.205.0 │
│ 84 1.839 1.237 1.839 1.237 1.07 1.834 2.807 │
│ 1.304 3.492.997.107-.775.418-1.305.762-1.604 │
│ -2.665-.305-5.467-1.334-5.467-5.931 0-1.311. │
│ 469-2.381 1.236-3.221-.124-.303-.535-1.524.1 │
│ 17-3.176 0 0 1.008-.322 3.301 1.23A11.509 11 │
│ .509 0 0112 5.803c1.02.005 2.047.138 3.006.4 │
│ 04 2.291-1.552 3.297-1.23 3.297-1.23.653 1.6 │
│ 53.242 2.874.118 3.176.77.84 1.235 1.911 1.2 │
│ 35 3.221 0 4.609-2.807 5.624-5.479 5.921.43. │
│ 372.823 1.102.823 2.222v3.293c0 .319.192.694 │
│ .801.576C20.566 21.797 24 17.300 24 12c0-6.6 │
│ 27-5.373-12-12-12z"/> │
└──────────────────────────────────────────────┘
┌─ web/src/layouts/ChartLayout.astro ────────────────────────────────────────┐
│ diff --git a/web/src/layouts/ChartLayout.astro b/web/src/layouts/ChartLayout.astro │
│ index 2faf73f..7c5a112 100644 │
│ --- a/web/src/layouts/ChartLayout.astro │
│ +++ b/web/src/layouts/ChartLayout.astro │
│ @@ -444,6 +444,23 @@ const isFixedClassSpec = fixedClass && fixedSpec; │
│ border-color: var(--highlight-color); │
│ } │
│ │
│ + .wowsim-button { │
│ + background-color: var(--bg-primary); │
│ + border-color: var(--border-color); │
│ + color: var(--text-primary); │
│ + margin-bottom: 12px; │
│ + display: block; │
│ + max-width: 200px; │
│ + text-align: center; │
│ + font-weight: bold; │
│ + } │
│ + │
│ + .wowsim-button:hover { │
│ + background-color: var(--bg-selection); │
│ + border-color: var(--highlight-color); │
│ + color: var(--highlight-color); │
│ + } │
│ + │
│ .equipment-grid { │
│ display: grid; │
│ grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); │
│ @@ -451,46 +468,193 @@ const isFixedClassSpec = fixedClass && fixedSpec; │
│ } │
│ │
│ .equipment-slot { │
│ - display: flex; │
│ - justify-content: space-between; │
│ - align-items: flex-start; │
│ padding: 8px; │
│ - background-color: rgba(255,255,255,0.05); │
│ - border-radius: 3px; │
│ - font-size: 0.85em; │
│ - gap: 12px; │
│ + background-color: rgba(255,255,255,0.02); │
│ + border-radius: 4px; │
│ + border: 1px solid rgba(255,255,255,0.05); │
│ + margin-bottom: 8px; │
│ + } │
│ + │
│ + .equipment-slot-header { │
│ + margin-bottom: 6px; │
│ } │
│ │
│ .equipment-slot-name { │
│ color: var(--text-muted); │
│ font-weight: 500; │
│ - min-width: 80px; │
│ + font-size: 0.8em; │
│ + text-transform: uppercase; │
│ + letter-spacing: 0.5px; │
│ + } │
│ + │
│ + .equipment-item-tooltip { │
│ + color: #fff; │
│ + font-size: 13px; │
│ + line-height: 1.4; │
│ + } │
│ + │
│ + .equipment-item-header { │
│ + display: flex; │
│ + align-items: flex-start; │
│ + gap: 8px; │
│ } │
│ │
│ .equipment-item-link { │
│ - color: #ffd100; │
│ + color: #fff; │
│ text-decoration: none; │
│ - font-family: 'Courier New', monospace; │
│ - font-size: 0.9em; │
│ + font-weight: bold; │
│ + font-size: 14px; │
│ + display: block; │
│ + margin-bottom: 4px; │
│ + text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.8); │
│ transition: color 0.2s ease; │
│ } │
│ │
│ .equipment-item-link:hover { │
│ - color: #ffed4e; │
│ text-decoration: underline; │
│ } │
│ │
│ .equipment-item-info { │
│ flex: 1; │
│ + } │
│ + │
│ + .equipment-item-details { │
│ + margin-top: 4px; │
│ + } │
│ + │
│ + .item-tooltip-details { │
│ + margin-top: 8px; │
│ + } │
│ + │
│ + .equipment-detail { │
│ + color: #40ff40; │
│ + font-size: 12px; │
│ + margin-bottom: 2px; │
│ + line-height: 1.3; │
│ + font-weight: 500; │
│ + } │
│ + │
│ + .equipment-icon { │
│ + width: 24px; │
│ + height: 24px; │
│ + border-radius: 3px; │
│ + flex-shrink: 0; │
│ + border: 1px solid #444; │
│ + } │
│ + │
│ + .item-level { │
│ + color: #fff; │
│ + font-weight: 500; │
│ + margin: 2px 0; │
│ + } │
│ + │
│ + .item-reforge { │
│ + color: #40ff40; │
│ + font-weight: 500; │
│ + margin: 2px 0; │
│ + } │
│ + │
│ + .gem-line { │
│ + display: flex; │
│ + align-items: center; │
│ + gap: 6px; │
│ + margin: 2px 0; │
│ + } │
│ + │
│ + .gem-icon-inline { │
│ + width: 16px; │
│ + height: 16px; │
│ + border-radius: 2px; │
│ + flex-shrink: 0; │
│ + } │
│ + │
│ + .gem-stats-white { │
│ + color: #fff; │
│ + font-weight: 500; │
│ + } │
│ + │
│ + .item-enchant { │
│ + color: #40ff40; │
│ + font-weight: 500; │
│ + margin: 2px 0; │
│ + } │
│ + │
│ + .talents-list { │
│ display: flex; │
│ flex-direction: column; │
│ - gap: 2px; │
│ + gap: 4px; │
│ } │
│ │
│ - .equipment-detail { │
│ - color: #1eff00; │
│ - font-size: 0.8em; │
│ - line-height: 1.2; │
│ + .talent-line { │
│ + display: flex; │
│ + align-items: center; │
│ + gap: 6px; │
│ + } │
│ + │
│ + .talent-icon-inline { │
│ + width: 16px; │
│ + height: 16px; │
│ + border-radius: 2px; │
│ + flex-shrink: 0; │
│ + } │
│ + │
│ + .talent-name { │
│ + color: #fff; │
│ + font-weight: bold; │
│ + font-size: 14px; │
│ + text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.8); │
│ + } │
│ + │
│ + .talent-link { │
│ + color: #fff; │
│ + font-weight: bold; │
│ + font-size: 14px; │
│ + text-decoration: none; │
│ + text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.8); │
│ + transition: color 0.2s ease; │
│ + } │
│ + │
│ + .talent-link:hover { │
│ + text-decoration: underline; │
│ + } │
│ + │
│ + .glyphs-list { │
│ + display: flex; │
│ + flex-direction: column; │
│ + gap: 4px; │
│ + } │
│ + │
│ + .glyph-line { │
│ + display: flex; │
│ + align-items: center; │
│ + gap: 6px; │
│ + } │
│ + │
│ + .glyph-icon-inline { │
│ + width: 16px; │
│ + height: 16px; │
│ + border-radius: 2px; │
│ + flex-shrink: 0; │
│ + } │
│ + │
│ + .glyph-name { │
│ + color: #fff; │
│ + font-weight: bold; │
│ + font-size: 14px; │
│ + text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.8); │
│ + } │
│ + │
│ + .glyph-link { │
│ + color: #fff; │
│ + font-weight: bold; │
│ + font-size: 14px; │
│ + text-decoration: none; │
│ + text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.8); │
│ + transition: color 0.2s ease; │
│ + } │
│ + │
│ + .glyph-link:hover { │
│ + text-decoration: underline; │
│ } │
│ │
│ .equipment-item { │
│ @@ -536,20 +700,8 @@ const isFixedClassSpec = fixedClass && fixedSpec; │
│ .equipment-item-link.quality-6, │
│ .equipment-item-link.quality-7 { │
│ text-decoration: none; │
│ - transition: all 0.2s ease; │
│ } │
│ │
│ - .equipment-item-link.quality-0:hover, │
│ - .equipment-item-link.quality-1:hover, │
│ - .equipment-item-link.quality-2:hover, │
│ - .equipment-item-link.quality-3:hover, │
│ - .equipment-item-link.quality-4:hover, │
│ - .equipment-item-link.quality-5:hover, │
│ - .equipment-item-link.quality-6:hover, │
│ - .equipment-item-link.quality-7:hover { │
│ - text-shadow: 0 0 4px currentColor; │
│ - transform: translateY(-1px); │
│ - } │
│ │
│ /* Glyph-specific styling */ │
│ .consumable-item-header img { │
│ @@ -753,10 +905,9 @@ const formatLoadout = (loadout) => { │
│ const sections = []; │
│ │
│ // Character Info │
│ - if (loadout.race || loadout.class || loadout.profession1 || loadout.profession2 │
│ ) { │
│ + if (loadout.race || loadout.profession1 || loadout.profession2) { │
│ const items = []; │
│ if (loadout.race) items.push({ label: 'Race', value: formatRace(loadout.race) │
│ }); │
│ - if (loadout.class) items.push({ label: 'Class', value: formatClass(loadout.cl │
│ ass) }); │
│ if (loadout.profession1) items.push({ label: 'Profession 1', value: loadout.p │
│ rofession1 }); │
│ if (loadout.profession2) items.push({ label: 'Profession 2', value: loadout.p │
│ rofession2 }); │
│ sections.push({ title: 'Character', items }); │
│ @@ -807,56 +958,101 @@ const formatClass = (className) => { │
│ }; │
│ │
│ const formatTalents = (talents) => { │
│ - const talentItems = []; │
│ - if (talents && talents.talents && Array.isArray(talents.talents)) { │
│ - talents.talents.forEach(talent => { │
│ - const iconUrl = talent.icon │
│ - ? `https://wow.zamimg.com/images/wow/icons/large/${talent.icon}.jpg` │
│ - : null; │
│ - const spellId = talent.spellId; │
│ - const wowheadUrl = spellId │
│ - ? `https://www.wowhead.com/mop-classic/spell=${spellId}` │
│ - : null; │
│ - │
│ - talentItems.push({ │
│ - label: `Tier ${talent.tier}`, │
│ - value: talent.name, │
│ - iconUrl: iconUrl, │
│ - wowheadUrl: wowheadUrl, │
│ - isTalent: true │
│ - }); │
│ - }); │
│ + if (!talents || !talents.talents || !Array.isArray(talents.talents)) { │
│ + return []; │
│ } │
│ - return talentItems; │
│ + │
│ + // Create a single talents item with all talents listed │
│ + const talentList = talents.talents.map(talent => { │
│ + const iconUrl = talent.icon │
│ + ? `https://wow.zamimg.com/images/wow/icons/small/${talent.icon}.jpg` │
│ + : null; │
│ + const iconHtml = iconUrl │
│ + ? `<img src="${iconUrl}" alt="${talent.name}" class="talent-icon-inline" lo │
│ ading="lazy" />` │
│ + : ''; │
│ + const wowheadUrl = talent.spellId │
│ + ? `https://www.wowhead.com/mop-classic/spell=${talent.spellId}` │
│ + : null; │
│ + const nameHtml = wowheadUrl │
│ + ? `<a href="${wowheadUrl}" target="_blank" class="talent-link">${talent.nam │
│ e}</a>` │
│ + : `<span class="talent-name">${talent.name}</span>`; │
│ + return `<div class="talent-line">${iconHtml}${nameHtml}</div>`; │
│ + }).join(''); │
│ + │
│ + return [{ │
│ + label: 'Talents', │
│ + value: `<div class="talents-list">${talentList}</div>`, │
│ + isTalentList: true │
│ + }]; │
│ }; │
│ │
│ const formatGlyphs = (glyphs) => { │
│ - const glyphItems = []; │
│ - ['major1', 'major2', 'major3', 'minor1', 'minor2', 'minor3'].forEach(slot => { │
│ + const glyphContainers = []; │
│ + │
│ + // Major Glyphs │
│ + const majorGlyphs = []; │
│ + ['major1', 'major2', 'major3'].forEach(slot => { │
│ if (glyphs[slot]) { │
│ const glyphName = glyphs[`${slot}Name`] || `Glyph ${glyphs[slot]}`; │
│ const iconUrl = glyphs[`${slot}Icon`] │
│ - ? `https://wow.zamimg.com/images/wow/icons/large/${glyphs[`${slot}Icon`]} │
│ .jpg` │
│ + ? `https://wow.zamimg.com/images/wow/icons/small/${glyphs[`${slot}Icon`]} │
│ .jpg` │
│ : null; │
│ - const quality = glyphs[`${slot}Quality`]; │
│ const spellId = glyphs[`${slot}SpellId`]; │
│ + const wowheadUrl = spellId │
│ + ? `https://www.wowhead.com/mop-classic/spell=${spellId}` │
│ + : `https://www.wowhead.com/mop-classic/item=${glyphs[slot]}`; │
│ │
│ - // Use spellId for wowhead link if available, otherwise fall back to item l │
│ ookup │
│ + const iconHtml = iconUrl │
│ + ? `<img src="${iconUrl}" alt="${glyphName}" class="glyph-icon-inline" loa │
│ ding="lazy" />` │
│ + : ''; │
│ + const nameHtml = wowheadUrl │
│ + ? `<a href="${wowheadUrl}" target="_blank" class="glyph-link">${glyphName │
│ }</a>` │
│ + : `<span class="glyph-name">${glyphName}</span>`; │
│ + majorGlyphs.push(`<div class="glyph-line">${iconHtml}${nameHtml}</div>`); │
│ + } │
│ + }); │
│ + │
│ + // Minor Glyphs │
│ + const minorGlyphs = []; │
│ + ['minor1', 'minor2', 'minor3'].forEach(slot => { │
│ + if (glyphs[slot]) { │
│ + const glyphName = glyphs[`${slot}Name`] || `Glyph ${glyphs[slot]}`; │
│ + const iconUrl = glyphs[`${slot}Icon`] │
│ + ? `https://wow.zamimg.com/images/wow/icons/small/${glyphs[`${slot}Icon`]} │
│ .jpg` │
│ + : null; │
│ + const spellId = glyphs[`${slot}SpellId`]; │
│ const wowheadUrl = spellId │
│ ? `https://www.wowhead.com/mop-classic/spell=${spellId}` │
│ : `https://www.wowhead.com/mop-classic/item=${glyphs[slot]}`; │
│ │
│ - glyphItems.push({ │
│ - label: slot.charAt(0).toUpperCase() + slot.slice(1), // Capitalize slot n │
│ ame │
│ - value: glyphName, │
│ - iconUrl: iconUrl, │
│ - quality: quality, │
│ - wowheadUrl: wowheadUrl, │
│ - isGlyph: true │
│ - }); │
│ + const iconHtml = iconUrl │
│ + ? `<img src="${iconUrl}" alt="${glyphName}" class="glyph-icon-inline" loa │
│ ding="lazy" />` │
│ + : ''; │
│ + const nameHtml = wowheadUrl │
│ + ? `<a href="${wowheadUrl}" target="_blank" class="glyph-link">${glyphName │
│ }</a>` │
│ + : `<span class="glyph-name">${glyphName}</span>`; │
│ + minorGlyphs.push(`<div class="glyph-line">${iconHtml}${nameHtml}</div>`); │
│ } │
│ }); │
│ - return glyphItems; │
│ + │
│ + // Add containers if glyphs exist │
│ + if (majorGlyphs.length > 0) { │
│ + glyphContainers.push({ │
│ + label: 'Major Glyphs', │
│ + value: `<div class="glyphs-list">${majorGlyphs.join('')}</div>`, │
│ + isGlyphList: true │
│ + }); │
│ + } │
│ + │
│ + if (minorGlyphs.length > 0) { │
│ + glyphContainers.push({ │
│ + label: 'Minor Glyphs', │
│ + value: `<div class="glyphs-list">${minorGlyphs.join('')}</div>`, │
│ + isGlyphList: true │
│ + }); │
│ + } │
│ + │
│ + return glyphContainers; │
│ }; │
│ │
│ const formatConsumables = (consumables) => { │
│ @@ -932,12 +1128,6 @@ const formatEquipmentSummary = (items) => { │
│ return equipment; │
│ }; │
│ │
│ -const generateRawJsonUrl = (chartData) => { │
│ - // Generate URL to the raw JSON file used for this simulation │
│ - const fileName = chartData.fileName || 'unknown.json'; │
│ - const dataPath = chartData.dataPath || '/data/'; │
│ - return `${dataPath}${fileName}`; │
│ -}; │
│ │
│ // Generate loadout dropdown HTML │
│ const generateLoadoutDropdown = (loadout, chartData) => { │
│ @@ -948,25 +1138,32 @@ const generateLoadoutDropdown = (loadout, chartData) => { │
│ if (section.isEquipment) { │
│ // Special handling for equipment │
│ const equipmentHtml = section.items.map(eq => { │
│ - const detailsHtml = eq.itemDetails && eq.itemDetails.length > 0 │
│ - ? eq.itemDetails.map(detail => `<div class="equipment-detail">${detail} │
│ </div>`).join('') │
│ - : ''; │
│ - │
│ const iconHtml = eq.iconUrl │
│ ? `<img src="${eq.iconUrl}" alt="${eq.itemName}" class="equipment-icon" │
│ loading="lazy" />` │
│ : ''; │
│ │
│ const qualityClass = eq.quality ? `quality-${eq.quality}` : ''; │
│ │
│ + // Enhanced tooltip-style details │
│ + const detailsHtml = eq.itemDetails && eq.itemDetails.length > 0 │
│ + ? `<div class="item-tooltip-details"> │
│ + ${eq.itemDetails.map(detail => `<div class="equipment-detail">${de │
│ tail}</div>`).join('')} │
│ + </div>` │
│ + : ''; │
│ + │
│ return ` │
│ <div class="equipment-slot"> │
│ - <span class="equipment-slot-name">${eq.slot}:</span> │
│ - <div class="equipment-item-info"> │
│ + <div class="equipment-slot-header"> │
│ + <span class="equipment-slot-name">${eq.slot}</span> │
│ + </div> │
│ + <div class="equipment-item-tooltip"> │
│ <div class="equipment-item-header"> │
│ ${iconHtml} │
│ <a href="${eq.wowheadUrl}" target="_blank" class="equipment-item- │
│ link ${qualityClass}">${eq.itemName}</a> │
│ </div> │
│ - ${detailsHtml} │
│ + <div class="equipment-item-details"> │
│ + ${detailsHtml} │
│ + </div> │
│ </div> │
│ </div> │
│ `; │
│ @@ -986,7 +1183,10 @@ const generateLoadoutDropdown = (loadout, chartData) => { │
│ const valueClass = item.isSpecial === 'talents' ? 'loadout-value loadout- │
│ talents' : 'loadout-value'; │
│ │
│ let valueContent; │
│ - if ((item.isItem || item.isGlyph || item.isTalent) && item.wowheadUrl) { │
│ + if (item.isTalentList || item.isGlyphList) { │
│ + // Special handling for talent and glyph lists │
│ + valueContent = item.value; │
│ + } else if ((item.isItem || item.isGlyph || item.isTalent) && item.wowhead │
│ Url) { │
│ const iconHtml = item.iconUrl │
│ ? `<img src="${item.iconUrl}" alt="${item.value}" class="consumable-i │
│ con" loading="lazy" />` │
│ : ''; │
│ @@ -1020,18 +1220,18 @@ const generateLoadoutDropdown = (loadout, chartData) => { │
│ } │
│ }).join(''); │
│ │
│ - const rawJsonUrl = generateRawJsonUrl(chartData); │
│ + // Create WowSim button if simLink is available │
│ + const wowSimButton = loadout.simLink │
│ + ? `<a href="${loadout.simLink}" target="_blank" class="loadout-button wowsim- │
│ button">Open in WoWSims</a>` │
│ + : ''; │
│ │
│ return ` │
│ <div class="chart-dropdown"> │
│ + ${wowSimButton} │
│ <div class="loadout-notice"> │
│ - <strong>Note:</strong> Loadout details are a work in progress. Some glyph │
│ s may show as IDs instead of names. │
│ + <strong>Note:</strong> Profile details are a work in progress. │
│ </div> │
│ ${sectionsHtml} │
│ - <div class="loadout-actions"> │
│ - <a href="${rawJsonUrl}" target="_blank" class="loadout-button">View Raw J │
│ SON</a> │
│ - <button class="loadout-button" onclick="alert('WowSims link coming soon!' │
│ )">Open in WowSims</button> │
│ - </div> │
│ </div> │
│ `; │
│ }; │
└────────────────────────────────────────────────────────────────────────────────────┘
┌─ ...src/layouts/ChartLayout.astro ───┐
│ diff --git a/web/src/layouts/ChartLayout.ast │
│ ro b/web/src/layouts/ChartLayout.astro │
│ index 2faf73f..7c5a112 100644 │
│ --- a/web/src/layouts/ChartLayout.astro │
│ +++ b/web/src/layouts/ChartLayout.astro │
│ @@ -444,6 +444,23 @@ const isFixedClassSpec │
│ = fixedClass && fixedSpec; │
│ border-color: var(--highlight-color │
│ ); │
│ } │
│ │
│ + .wowsim-button { │
│ + background-color: var(--bg-primary) │
│ ; │
│ + border-color: var(--border-color); │
│ + color: var(--text-primary); │
│ + margin-bottom: 12px; │
│ + display: block; │
│ + max-width: 200px; │
│ + text-align: center; │
│ + font-weight: bold; │
│ + } │
│ + │
│ + .wowsim-button:hover { │
│ + background-color: var(--bg-selectio │
│ n); │
│ + border-color: var(--highlight-color │
│ ); │
│ + color: var(--highlight-color); │
│ + } │
│ + │
│ .equipment-grid { │
│ display: grid; │
│ grid-template-columns: repeat(auto- │
│ fit, minmax(250px, 1fr)); │
│ @@ -451,46 +468,193 @@ const isFixedClassSpe │
│ c = fixedClass && fixedSpec; │
│ } │
│ │
│ .equipment-slot { │
│ - display: flex; │
│ - justify-content: space-between; │
│ - align-items: flex-start; │
│ padding: 8px; │
│ - background-color: rgba(255,255,255, │
│ 0.05); │
│ - border-radius: 3px; │
│ - font-size: 0.85em; │
│ - gap: 12px; │
│ + background-color: rgba(255,255,255, │
│ 0.02); │
│ + border-radius: 4px; │
│ + border: 1px solid rgba(255,255,255, │
│ 0.05); │
│ + margin-bottom: 8px; │
│ + } │
│ + │
│ + .equipment-slot-header { │
│ + margin-bottom: 6px; │
│ } │
│ │
│ .equipment-slot-name { │
│ color: var(--text-muted); │
│ font-weight: 500; │
│ - min-width: 80px; │
│ + font-size: 0.8em; │
│ + text-transform: uppercase; │
│ + letter-spacing: 0.5px; │
│ + } │
│ + │
│ + .equipment-item-tooltip { │
│ + color: #fff; │
│ + font-size: 13px; │
│ + line-height: 1.4; │
│ + } │
│ + │
│ + .equipment-item-header { │
│ + display: flex; │
│ + align-items: flex-start; │
│ + gap: 8px; │
│ } │
│ │
│ .equipment-item-link { │
│ - color: #ffd100; │
│ + color: #fff; │
│ text-decoration: none; │
│ - font-family: 'Courier New', monospa │
│ ce; │
│ - font-size: 0.9em; │
│ + font-weight: bold; │
│ + font-size: 14px; │
│ + display: block; │
│ + margin-bottom: 4px; │
│ + text-shadow: 1px 1px 2px rgba(0, 0, │
│ 0, 0.8); │
│ transition: color 0.2s ease; │
│ } │
│ │
│ .equipment-item-link:hover { │
│ - color: #ffed4e; │
│ text-decoration: underline; │
│ } │
│ │
│ .equipment-item-info { │
│ flex: 1; │
│ + } │
│ + │
│ + .equipment-item-details { │
│ + margin-top: 4px; │
│ + } │
│ + │
│ + .item-tooltip-details { │
│ + margin-top: 8px; │
│ + } │
│ + │
│ + .equipment-detail { │
│ + color: #40ff40; │
│ + font-size: 12px; │
│ + margin-bottom: 2px; │
│ + line-height: 1.3; │
│ + font-weight: 500; │
│ + } │
│ + │
│ + .equipment-icon { │
│ + width: 24px; │
│ + height: 24px; │
│ + border-radius: 3px; │
│ + flex-shrink: 0; │
│ + border: 1px solid #444; │
│ + } │
│ + │
│ + .item-level { │
│ + color: #fff; │
│ + font-weight: 500; │
│ + margin: 2px 0; │
│ + } │
│ + │
│ + .item-reforge { │
│ + color: #40ff40; │
│ + font-weight: 500; │
│ + margin: 2px 0; │
│ + } │
│ + │
│ + .gem-line { │
│ + display: flex; │
│ + align-items: center; │
│ + gap: 6px; │
│ + margin: 2px 0; │
│ + } │
│ + │
│ + .gem-icon-inline { │
│ + width: 16px; │
│ + height: 16px; │
│ + border-radius: 2px; │
│ + flex-shrink: 0; │
│ + } │
│ + │
│ + .gem-stats-white { │
│ + color: #fff; │
│ + font-weight: 500; │
│ + } │
│ + │
│ + .item-enchant { │
│ + color: #40ff40; │
│ + font-weight: 500; │
│ + margin: 2px 0; │
│ + } │
│ + │
│ + .talents-list { │
│ display: flex; │
│ flex-direction: column; │
│ - gap: 2px; │
│ + gap: 4px; │
│ } │
│ │
│ - .equipment-detail { │
│ - color: #1eff00; │
│ - font-size: 0.8em; │
│ - line-height: 1.2; │
│ + .talent-line { │
│ + display: flex; │
│ + align-items: center; │
│ + gap: 6px; │
│ + } │
│ + │
│ + .talent-icon-inline { │
│ + width: 16px; │
│ + height: 16px; │
│ + border-radius: 2px; │
│ + flex-shrink: 0; │
│ + } │
│ + │
│ + .talent-name { │
│ + color: #fff; │
│ + font-weight: bold; │
│ + font-size: 14px; │
│ + text-shadow: 1px 1px 2px rgba(0, 0, │
│ 0, 0.8); │
│ + } │
│ + │
│ + .talent-link { │
│ + color: #fff; │
│ + font-weight: bold; │
│ + font-size: 14px; │
│ + text-decoration: none; │
│ + text-shadow: 1px 1px 2px rgba(0, 0, │
│ 0, 0.8); │
│ + transition: color 0.2s ease; │
│ + } │
│ + │
│ + .talent-link:hover { │
│ + text-decoration: underline; │
│ + } │
│ + │
│ + .glyphs-list { │
│ + display: flex; │
│ + flex-direction: column; │
│ + gap: 4px; │
│ + } │
│ + │
│ + .glyph-line { │
│ + display: flex; │
│ + align-items: center; │
│ + gap: 6px; │
│ + } │
│ + │
│ + .glyph-icon-inline { │
│ + width: 16px; │
│ + height: 16px; │
│ + border-radius: 2px; │
│ + flex-shrink: 0; │
│ + } │
│ + │
│ + .glyph-name { │
│ + color: #fff; │
│ + font-weight: bold; │
│ + font-size: 14px; │
│ + text-shadow: 1px 1px 2px rgba(0, 0, │
│ 0, 0.8); │
│ + } │
│ + │
│ + .glyph-link { │
│ + color: #fff; │
│ + font-weight: bold; │
│ + font-size: 14px; │
│ + text-decoration: none; │
│ + text-shadow: 1px 1px 2px rgba(0, 0, │
│ 0, 0.8); │
│ + transition: color 0.2s ease; │
│ + } │
│ + │
│ + .glyph-link:hover { │
│ + text-decoration: underline; │
│ } │
│ │
│ .equipment-item { │
│ @@ -536,20 +700,8 @@ const isFixedClassSpec │
│ = fixedClass && fixedSpec; │
│ .equipment-item-link.quality-6, │
│ .equipment-item-link.quality-7 { │
│ text-decoration: none; │
│ - transition: all 0.2s ease; │
│ } │
│ │
│ - .equipment-item-link.quality-0:hover, │
│ - .equipment-item-link.quality-1:hover, │
│ - .equipment-item-link.quality-2:hover, │
│ - .equipment-item-link.quality-3:hover, │
│ - .equipment-item-link.quality-4:hover, │
│ - .equipment-item-link.quality-5:hover, │
│ - .equipment-item-link.quality-6:hover, │
│ - .equipment-item-link.quality-7:hover │
│ { │
│ - text-shadow: 0 0 4px currentColor; │
│ - transform: translateY(-1px); │
│ - } │
│ │
│ /* Glyph-specific styling */ │
│ .consumable-item-header img { │
│ @@ -753,10 +905,9 @@ const formatLoadout = ( │
│ loadout) => { │
│ const sections = []; │
│ │
│ // Character Info │
│ - if (loadout.race || loadout.class || load │
│ out.profession1 || loadout.profession2) { │
│ + if (loadout.race || loadout.profession1 | │
│ | loadout.profession2) { │
│ const items = []; │
│ if (loadout.race) items.push({ label: ' │
│ Race', value: formatRace(loadout.race) }); │
│ - if (loadout.class) items.push({ label: │
│ 'Class', value: formatClass(loadout.class) } │
│ ); │
│ if (loadout.profession1) items.push({ l │
│ abel: 'Profession 1', value: loadout.profess │
│ ion1 }); │
│ if (loadout.profession2) items.push({ l │
│ abel: 'Profession 2', value: loadout.profess │
│ ion2 }); │
│ sections.push({ title: 'Character', ite │
│ ms }); │
│ @@ -807,56 +958,101 @@ const formatClass = ( │
│ className) => { │
│ }; │
│ │
│ const formatTalents = (talents) => { │
│ - const talentItems = []; │
│ - if (talents && talents.talents && Array.i │
│ sArray(talents.talents)) { │
│ - talents.talents.forEach(talent => { │
│ - const iconUrl = talent.icon │
│ - ? `https://wow.zamimg.com/images/wo │
│ w/icons/large/${talent.icon}.jpg` │
│ - : null; │
│ - const spellId = talent.spellId; │
│ - const wowheadUrl = spellId │
│ - ? `https://www.wowhead.com/mop-clas │
│ sic/spell=${spellId}` │
│ - : null; │
│ - │
│ - talentItems.push({ │
│ - label: `Tier ${talent.tier}`, │
│ - value: talent.name, │
│ - iconUrl: iconUrl, │
│ - wowheadUrl: wowheadUrl, │
│ - isTalent: true │
│ - }); │
│ - }); │
│ + if (!talents || !talents.talents || !Arra │
│ y.isArray(talents.talents)) { │
│ + return []; │
│ } │
│ - return talentItems; │
│ + │
│ + // Create a single talents item with all │
│ talents listed │
│ + const talentList = talents.talents.map(ta │
│ lent => { │
│ + const iconUrl = talent.icon │
│ + ? `https://wow.zamimg.com/images/wow/ │
│ icons/small/${talent.icon}.jpg` │
│ + : null; │
│ + const iconHtml = iconUrl │
│ + ? `<img src="${iconUrl}" alt="${talen │
│ t.name}" class="talent-icon-inline" loading= │
│ "lazy" />` │
│ + : ''; │
│ + const wowheadUrl = talent.spellId │
│ + ? `https://www.wowhead.com/mop-classi │
│ c/spell=${talent.spellId}` │
│ + : null; │
│ + const nameHtml = wowheadUrl │
│ + ? `<a href="${wowheadUrl}" target="_b │
│ lank" class="talent-link">${talent.name}</a> │
│ ` │
│ + : `<span class="talent-name">${talent │
│ .name}</span>`; │
│ + return `<div class="talent-line">${icon │
│ Html}${nameHtml}</div>`; │
│ + }).join(''); │
│ + │
│ + return [{ │
│ + label: 'Talents', │
│ + value: `<div class="talents-list">${tal │
│ entList}</div>`, │
│ + isTalentList: true │
│ + }]; │
│ }; │
│ │
│ const formatGlyphs = (glyphs) => { │
│ - const glyphItems = []; │
│ - ['major1', 'major2', 'major3', 'minor1', │
│ 'minor2', 'minor3'].forEach(slot => { │
│ + const glyphContainers = []; │
│ + │
│ + // Major Glyphs │
│ + const majorGlyphs = []; │
│ + ['major1', 'major2', 'major3'].forEach(sl │
│ ot => { │
│ if (glyphs[slot]) { │
│ const glyphName = glyphs[`${slot}Name │
│ `] || `Glyph ${glyphs[slot]}`; │
│ const iconUrl = glyphs[`${slot}Icon`] │
│ │
│ - ? `https://wow.zamimg.com/images/wo │
│ w/icons/large/${glyphs[`${slot}Icon`]}.jpg` │
│ + ? `https://wow.zamimg.com/images/wo │
│ w/icons/small/${glyphs[`${slot}Icon`]}.jpg` │
│ : null; │
│ - const quality = glyphs[`${slot}Qualit │
│ y`]; │
│ const spellId = glyphs[`${slot}SpellI │
│ d`]; │
│ + const wowheadUrl = spellId │
│ + ? `https://www.wowhead.com/mop-clas │
│ sic/spell=${spellId}` │
│ + : `https://www.wowhead.com/mop-clas │
│ sic/item=${glyphs[slot]}`; │
│ │
│ - // Use spellId for wowhead link if av │
│ ailable, otherwise fall back to item lookup │
│ + const iconHtml = iconUrl │
│ + ? `<img src="${iconUrl}" alt="${gly │
│ phName}" class="glyph-icon-inline" loading=" │
│ lazy" />` │
│ + : ''; │
│ + const nameHtml = wowheadUrl │
│ + ? `<a href="${wowheadUrl}" target=" │
│ _blank" class="glyph-link">${glyphName}</a>` │
│ + : `<span class="glyph-name">${glyph │
│ Name}</span>`; │
│ + majorGlyphs.push(`<div class="glyph-l │
│ ine">${iconHtml}${nameHtml}</div>`); │
│ + } │
│ + }); │
│ + │
│ + // Minor Glyphs │
│ + const minorGlyphs = []; │
│ + ['minor1', 'minor2', 'minor3'].forEach(sl │
│ ot => { │
│ + if (glyphs[slot]) { │
│ + const glyphName = glyphs[`${slot}Name │
│ `] || `Glyph ${glyphs[slot]}`; │
│ + const iconUrl = glyphs[`${slot}Icon`] │
│ │
│ + ? `https://wow.zamimg.com/images/wo │
│ w/icons/small/${glyphs[`${slot}Icon`]}.jpg` │
│ + : null; │
│ + const spellId = glyphs[`${slot}SpellI │
│ d`]; │
│ const wowheadUrl = spellId │
│ ? `https://www.wowhead.com/mop-clas │
│ sic/spell=${spellId}` │
│ : `https://www.wowhead.com/mop-clas │
│ sic/item=${glyphs[slot]}`; │
│ │
│ - glyphItems.push({ │
│ - label: slot.charAt(0).toUpperCase() │
│ + slot.slice(1), // Capitalize slot name │
│ - value: glyphName, │
│ - iconUrl: iconUrl, │
│ - quality: quality, │
│ - wowheadUrl: wowheadUrl, │
│ - isGlyph: true │
│ - }); │
│ + const iconHtml = iconUrl │
│ + ? `<img src="${iconUrl}" alt="${gly │
│ phName}" class="glyph-icon-inline" loading=" │
│ lazy" />` │
│ + : ''; │
│ + const nameHtml = wowheadUrl │
│ + ? `<a href="${wowheadUrl}" target=" │
│ _blank" class="glyph-link">${glyphName}</a>` │
│ + : `<span class="glyph-name">${glyph │
│ Name}</span>`; │
│ + minorGlyphs.push(`<div class="glyph-l │
│ ine">${iconHtml}${nameHtml}</div>`); │
│ } │
│ }); │
│ - return glyphItems; │
│ + │
│ + // Add containers if glyphs exist │
│ + if (majorGlyphs.length > 0) { │
│ + glyphContainers.push({ │
│ + label: 'Major Glyphs', │
│ + value: `<div class="glyphs-list">${ma │
│ jorGlyphs.join('')}</div>`, │
│ + isGlyphList: true │
│ + }); │
│ + } │
│ + │
│ + if (minorGlyphs.length > 0) { │
│ + glyphContainers.push({ │
│ + label: 'Minor Glyphs', │
│ + value: `<div class="glyphs-list">${mi │
│ norGlyphs.join('')}</div>`, │
│ + isGlyphList: true │
│ + }); │
│ + } │
│ + │
│ + return glyphContainers; │
│ }; │
│ │
│ const formatConsumables = (consumables) => │
│ { │
│ @@ -932,12 +1128,6 @@ const formatEquipmentS │
│ ummary = (items) => { │
│ return equipment; │
│ }; │
│ │
│ -const generateRawJsonUrl = (chartData) => { │
│ - // Generate URL to the raw JSON file used │
│ for this simulation │
│ - const fileName = chartData.fileName || 'u │
│ nknown.json'; │
│ - const dataPath = chartData.dataPath || '/ │
│ data/'; │
│ - return `${dataPath}${fileName}`; │
│ -}; │
│ │
│ // Generate loadout dropdown HTML │
│ const generateLoadoutDropdown = (loadout, c │
│ hartData) => { │
│ @@ -948,25 +1138,32 @@ const generateLoadout │
│ Dropdown = (loadout, chartData) => { │
│ if (section.isEquipment) { │
│ // Special handling for equipment │
│ const equipmentHtml = section.items.m │
│ ap(eq => { │
│ - const detailsHtml = eq.itemDetails │
│ && eq.itemDetails.length > 0 │
│ - ? eq.itemDetails.map(detail => `< │
│ div class="equipment-detail">${detail}</div> │
│ `).join('') │
│ - : ''; │
│ - │
│ const iconHtml = eq.iconUrl │
│ ? `<img src="${eq.iconUrl}" alt=" │
│ ${eq.itemName}" class="equipment-icon" loadi │
│ ng="lazy" />` │
│ : ''; │
│ │
│ const qualityClass = eq.quality ? ` │
│ quality-${eq.quality}` : ''; │
│ │
│ + // Enhanced tooltip-style details │
│ + const detailsHtml = eq.itemDetails │
│ && eq.itemDetails.length > 0 │
│ + ? `<div class="item-tooltip-detai │
│ ls"> │
│ + ${eq.itemDetails.map(detail │
│ => `<div class="equipment-detail">${detail}< │
│ /div>`).join('')} │
│ + </div>` │
│ + : ''; │
│ + │
│ return ` │
│ <div class="equipment-slot"> │
│ - <span class="equipment-slot-nam │
│ e">${eq.slot}:</span> │
│ - <div class="equipment-item-info │
│ "> │
│ + <div class="equipment-slot-head │
│ er"> │
│ + <span class="equipment-slot-n │
│ ame">${eq.slot}</span> │
│ + </div> │
│ + <div class="equipment-item-tool │
│ tip"> │
│ <div class="equipment-item-he │
│ ader"> │
│ ${iconHtml} │
│ <a href="${eq.wowheadUrl}" │
│ target="_blank" class="equipment-item-link $ │
│ {qualityClass}">${eq.itemName}</a> │
│ </div> │
│ - ${detailsHtml} │
│ + <div class="equipment-item-de │
│ tails"> │
│ + ${detailsHtml} │
│ + </div> │
│ </div> │
│ </div> │
│ `; │
│ @@ -986,7 +1183,10 @@ const generateLoadoutD │
│ ropdown = (loadout, chartData) => { │
│ const valueClass = item.isSpecial = │
│ == 'talents' ? 'loadout-value loadout-talent │
│ s' : 'loadout-value'; │
│ │
│ let valueContent; │
│ - if ((item.isItem || item.isGlyph || │
│ item.isTalent) && item.wowheadUrl) { │
│ + if (item.isTalentList || item.isGly │
│ phList) { │
│ + // Special handling for talent an │
│ d glyph lists │
│ + valueContent = item.value; │
│ + } else if ((item.isItem || item.isG │
│ lyph || item.isTalent) && item.wowheadUrl) { │
│ const iconHtml = item.iconUrl │
│ ? `<img src="${item.iconUrl}" a │
│ lt="${item.value}" class="consumable-icon" l │
│ oading="lazy" />` │
│ : ''; │
│ @@ -1020,18 +1220,18 @@ const generateLoadou │
│ tDropdown = (loadout, chartData) => { │
│ } │
│ }).join(''); │
│ │
│ - const rawJsonUrl = generateRawJsonUrl(cha │
│ rtData); │
│ + // Create WowSim button if simLink is ava │
│ ilable │
│ + const wowSimButton = loadout.simLink │
│ + ? `<a href="${loadout.simLink}" target= │
│ "_blank" class="loadout-button wowsim-button │
│ ">Open in WoWSims</a>` │
│ + : ''; │
│ │
│ return ` │
│ <div class="chart-dropdown"> │
│ + ${wowSimButton} │
│ <div class="loadout-notice"> │
│ - <strong>Note:</strong> Loadout deta │
│ ils are a work in progress. Some glyphs may │
│ show as IDs instead of names. │
│ + <strong>Note:</strong> Profile deta │
│ ils are a work in progress. │
│ </div> │
│ ${sectionsHtml} │
│ - <div class="loadout-actions"> │
│ - <a href="${rawJsonUrl}" target="_bl │
│ ank" class="loadout-button">View Raw JSON</a │
│ > │
│ - <button class="loadout-button" oncl │
│ ick="alert('WowSims link coming soon!')">Ope │
│ n in WowSims</button> │
│ - </div> │
│ </div> │
│ `; │
│ }; │
└──────────────────────────────────────────────┘
[ BACK TO LOG ]
──────────────────────────────────────────────────────────────────────────────────────
OOKNET
────────────────────────────────────────────────
OOKNET