OOKNET                             [ /  search the index  ]  
──────────────────────────────────────────────────────────────────────────────────────
══════════════════════════════════════════════════════════════════════════════════════
OOKNET   [ /  search  ]  
────────────────────────────────────────────────
════════════════════════════════════════════════
 
 
master @ 113 LINES
 
[ HISTORY ]  [ UP ]
 

---
import "./GearSlotCard.scss";
import type { GearSlotBucket } from "../../../lib/types";
import ItemTooltip from "../../ItemTooltip/ItemTooltip.astro";

interface Props {
  slot: string;
  label: string;
  bucket: GearSlotBucket | undefined;
  // cap items per slot to keep long-tail noise out
  limit?: number;
  // hide items below this share % of players_with_slot
  minSharePct?: number;
  // Blizzard down-scales every CM piece to ilvl 463, so the tooltip should
  // show that level (not the player's actual upgraded ilvl)
  tooltipIlvl?: number;
}

const {
  slot,
  label,
  bucket,
  limit = 8,
  minSharePct = 0,
  tooltipIlvl = 463,
} = Astro.props;

const playersWithSlot = bucket?.players_with_slot ?? 0;
const allItems = bucket?.items ?? [];
const items = allItems
  .filter((item) => {
    if (playersWithSlot === 0) return false;
    return (item.count / playersWithSlot) * 100 >= minSharePct;
  })
  .slice(0, limit);

function pct(count: number): number {
  if (!playersWithSlot) return 0;
  return (count / playersWithSlot) * 100;
}

function iconUrl(icon: string | undefined): string | null {
  if (!icon) return null;
  return `https://wow.zamimg.com/images/wow/icons/medium/${icon}.jpg`;
}

function qualityClass(q: number): string {
  switch (q) {
    case 5:
      return "quality-legendary";
    case 4:
      return "quality-epic";
    case 3:
      return "quality-rare";
    case 2:
      return "quality-uncommon";
    case 7:
      return "quality-heirloom";
    default:
      return "quality-common";
  }
}
---

<article class="gear-slot-card">
  <header class="gear-slot-card__header">
    <span class="gear-slot-card__slot">{label}</span>
    {bucket && <span class="gear-slot-card__pool">{playersWithSlot} runs</span>}
  </header>

  {
    items.length > 0 ? (
      <ul class="gear-slot-card__bars">
        {items.map((item) => {
          const sharePct = pct(item.count);
          return (
            <li class="gear-slot-card__row">
              <ItemTooltip
                itemId={item.item_id}
                ilvl={tooltipIlvl}
                class={`gear-slot-card__icon-link ${qualityClass(item.quality)}`}
                ariaLabel={item.name}
              >
                {iconUrl(item.icon) ? (
                  <img
                    class="gear-slot-card__icon"
                    src={iconUrl(item.icon)}
                    alt={item.name}
                    loading="lazy"
                  />
                ) : (
                  <span class="gear-slot-card__icon-fallback" />
                )}
              </ItemTooltip>
              <div class="gear-slot-card__bar-track" aria-hidden="true">
                <div
                  class="gear-slot-card__bar-fill"
                  style={`width: ${sharePct.toFixed(1)}%`}
                />
                <span class="gear-slot-card__bar-label">
                  {sharePct.toFixed(0)}%
                </span>
              </div>
            </li>
          );
        })}
      </ul>
    ) : (
      <p class="gear-slot-card__empty">No data</p>
    )
  }
</article>

---
import "./GearSlotCard.scss";
import type { GearSlotBucket } from "../../.
./lib/types";
import ItemTooltip from "../../ItemTooltip/I
temTooltip.astro";

interface Props {
  slot: string;
  label: string;
  bucket: GearSlotBucket | undefined;
  // cap items per slot to keep long-tail no
ise out
  limit?: number;
  // hide items below this share % of player
s_with_slot
  minSharePct?: number;
  // Blizzard down-scales every CM piece to 
ilvl 463, so the tooltip should
  // show that level (not the player's actua
l upgraded ilvl)
  tooltipIlvl?: number;
}

const {
  slot,
  label,
  bucket,
  limit = 8,
  minSharePct = 0,
  tooltipIlvl = 463,
} = Astro.props;

const playersWithSlot = bucket?.players_with
_slot ?? 0;
const allItems = bucket?.items ?? [];
const items = allItems
  .filter((item) => {
    if (playersWithSlot === 0) return false;
    return (item.count / playersWithSlot) * 
100 >= minSharePct;
  })
  .slice(0, limit);

function pct(count: number): number {
  if (!playersWithSlot) return 0;
  return (count / playersWithSlot) * 100;
}

function iconUrl(icon: string | undefined): 
string | null {
  if (!icon) return null;
  return `https://wow.zamimg.com/images/wow/
icons/medium/${icon}.jpg`;
}

function qualityClass(q: number): string {
  switch (q) {
    case 5:
      return "quality-legendary";
    case 4:
      return "quality-epic";
    case 3:
      return "quality-rare";
    case 2:
      return "quality-uncommon";
    case 7:
      return "quality-heirloom";
    default:
      return "quality-common";
  }
}
---

<article class="gear-slot-card">
  <header class="gear-slot-card__header">
    <span class="gear-slot-card__slot">{labe
l}</span>
    {bucket && <span class="gear-slot-card__
pool">{playersWithSlot} runs</span>}
  </header>

  {
    items.length > 0 ? (
      <ul class="gear-slot-card__bars">
        {items.map((item) => {
          const sharePct = pct(item.count);
          return (
            <li class="gear-slot-card__row">
              <ItemTooltip
                itemId={item.item_id}
                ilvl={tooltipIlvl}
                class={`gear-slot-card__icon
-link ${qualityClass(item.quality)}`}
                ariaLabel={item.name}
              >
                {iconUrl(item.icon) ? (
                  <img
                    class="gear-slot-card__i
con"
                    src={iconUrl(item.icon)}
                    alt={item.name}
                    loading="lazy"
                  />
                ) : (
                  <span class="gear-slot-car
d__icon-fallback" />
                )}
              </ItemTooltip>
              <div class="gear-slot-card__ba
r-track" aria-hidden="true">
                <div
                  class="gear-slot-card__bar
-fill"
                  style={`width: ${sharePct.
toFixed(1)}%`}
                />
                <span class="gear-slot-card_
_bar-label">
                  {sharePct.toFixed(0)}%
                </span>
              </div>
            </li>
          );
        })}
      </ul>
    ) : (
      <p class="gear-slot-card__empty">No da
ta</p>
    )
  }
</article>
 
──────────────────────────────────────────────────────────────────────────────────────
OOKNET
────────────────────────────────────────────────
OOKNET