diff --git a/ui/core/components/gear_picker.tsx b/ui/core/components/gear_picker.tsx index 97687b2fe1..0072f51e65 100644 --- a/ui/core/components/gear_picker.tsx +++ b/ui/core/components/gear_picker.tsx @@ -1,4 +1,4 @@ -import { classNames, difficultyNames, professionNames, slotNames } from '../proto_utils/names.js'; +import { difficultyNames, professionNames, slotNames } from '../proto_utils/names.js'; import { BaseModal } from './base_modal'; import { Component } from './component'; import { FiltersMenu } from './filters_menu'; @@ -125,7 +125,7 @@ export class ItemRenderer extends Component { readonly socketsContainerElem: HTMLElement; constructor(parent: HTMLElement, player: Player) { - super(parent, 'item-picker-root'); + super(parent, 'item-renderer-root'); this.player = player; let iconElem = ref(); @@ -1309,4 +1309,4 @@ export class ItemList { } return <>; } -} \ No newline at end of file +} diff --git a/ui/core/components/individual_sim_ui/gear_tab.ts b/ui/core/components/individual_sim_ui/gear_tab.ts index 3800049916..db11ae7f7c 100644 --- a/ui/core/components/individual_sim_ui/gear_tab.ts +++ b/ui/core/components/individual_sim_ui/gear_tab.ts @@ -9,6 +9,7 @@ import { Stats } from "../../proto_utils/stats"; import { GearPicker } from "../gear_picker"; import { SavedDataManager } from "../saved_data_manager"; import { SimTab } from "../sim_tab"; +import { GemSummary } from "./gem_summary"; export class GearTab extends SimTab { protected simUI: IndividualSimUI; @@ -34,7 +35,7 @@ export class GearTab extends SimTab { protected buildTabContent() { this.buildGearPickers(); - + this.buildGemSummary(); this.buildSavedGearsetPicker(); } @@ -42,6 +43,10 @@ export class GearTab extends SimTab { new GearPicker(this.leftPanel, this.simUI, this.simUI.player); } + private buildGemSummary() { + new GemSummary(this.leftPanel, this.simUI, this.simUI.player); + } + private buildSavedGearsetPicker() { const savedGearManager = new SavedDataManager, SavedGearSet>(this.rightPanel, this.simUI.player, { header: { title: "Gear Sets" }, diff --git a/ui/core/components/individual_sim_ui/gem_summary.ts b/ui/core/components/individual_sim_ui/gem_summary.ts new file mode 100644 index 0000000000..7091d14422 --- /dev/null +++ b/ui/core/components/individual_sim_ui/gem_summary.ts @@ -0,0 +1,72 @@ +import { SimUI } from "../../sim_ui"; +import { Component } from "../../components/component"; +import { Player } from "../../player"; +import { setItemQualityCssClass } from "../../css_utils"; +import { ActionId } from "../../proto_utils/action_id"; +import { UIGem as Gem } from '../../proto/ui.js'; +import { ContentBlock } from "../content_block"; + +interface GemSummaryData { + gem: Gem + count: number +} + +export class GemSummary extends Component { + private readonly simUI: SimUI; + private readonly player: Player; + + private readonly container: ContentBlock; + + constructor(parent: HTMLElement, simUI: SimUI, player: Player) { + super(parent, 'gem-summary-root'); + this.simUI = simUI; + this.player = player; + + this.container = new ContentBlock(this.rootElem, 'gem-summary-container', { + header: {title: 'Gem Summary'} + }); + player.gearChangeEmitter.on(() => this.updateTable()); + } + + private updateTable() { + this.container.bodyElement.innerHTML = ``; + const fullGemList = this.player.getGear().getAllGems(this.player.isBlacksmithing()); + const gemCounts: Record = {}; + + for (const gem of fullGemList) { + if (gemCounts[gem.name]) { + gemCounts[gem.name].count += 1 + } else { + gemCounts[gem.name] = { + gem: gem, + count: 1, + } + } + } + + for (const gemName of Object.keys(gemCounts)) { + const gemData = gemCounts[gemName] + const row = document.createElement('div'); + row.classList.add('d-flex', 'align-items-center', 'justify-content-between') + row.innerHTML = ` + + +
${gemName}
+
+
${gemData.count.toFixed(0)}
+ `; + + const gemLinkElem = row.querySelector('.gem-summary-link') as HTMLAnchorElement; + const gemIconElem = row.querySelector('.gem-icon') as HTMLImageElement; + + setItemQualityCssClass(gemLinkElem, gemData.gem.quality); + + ActionId.fromItemId(gemData.gem.id).fill().then(filledId => { + gemIconElem.src = filledId.iconUrl; + filledId.setWowheadHref(gemLinkElem); + }); + + this.container.bodyElement.appendChild(row); + } + } +} diff --git a/ui/scss/core/components/_gear_picker.scss b/ui/scss/core/components/_gear_picker.scss index 6354338f94..842bfcadcb 100644 --- a/ui/scss/core/components/_gear_picker.scss +++ b/ui/scss/core/components/_gear_picker.scss @@ -3,9 +3,9 @@ @import "./filters_menu"; .gear-picker-root { + margin-bottom: var(--container-padding); display: flex; flex-wrap: wrap; - width: 100%; .gear-picker-left, .gear-picker-right { @@ -19,6 +19,11 @@ margin-bottom: $block-spacer; } + .item-renderer-root { + width: 100%; + display: flex; + } + .item-picker-icon { @include wowhead-background-icon; width: 4rem; @@ -29,18 +34,20 @@ .gear-picker-left { .item-picker-root { - flex-direction: row; - text-align: left; - // Add space to separate weapon categories &:nth-child(6) { - margin-bottom: map.get($spacers, 5); + margin-bottom: var(--container-padding); + } + + .item-renderer-root { + flex-direction: row; + text-align: left; } } } .gear-picker-right { - .item-picker-root { + .item-renderer-root { flex-direction: row-reverse; text-align: right; } @@ -85,25 +92,14 @@ } } -@include media-breakpoint-down(xl) { - .gear-picker-right { - margin-bottom: 2 * map.get($spacers, 3); - } -} - @include media-breakpoint-down(md) { .gear-picker-root { - .gear-picker-left { - .item-picker-root:last-child { - margin-bottom: map.get($spacers, 5); - } - } + flex-direction: column; + .gear-picker-left, .gear-picker-right { - .item-picker-root { - flex-direction: row; - text-align: left; - } + width: 100%; + margin-right: 0; } } } @@ -125,18 +121,27 @@ } } -@include media-breakpoint-down(md) { +@include media-breakpoint-down(xl) { .gear-picker-root { .gear-picker-left { - .item-picker-root:last-child { - margin-bottom: map.get($spacers, 5); + .item-picker-root { + // Increase the spacing to help separate the weapons/bonus item slots + &:nth-child(6) { + margin-bottom: calc(var(--container-padding) * 2); + } } } + } +} - .gear-picker-right { +@include media-breakpoint-down(md) { + .gear-picker-root { + .gear-picker-left { .item-picker-root { - flex-direction: row; - text-align: left; + // Increase the spacing to help separate the weapons/bonus item slots + &:last-child { + margin-bottom: calc(var(--container-padding) * 2); + } } } } diff --git a/ui/scss/core/components/_sim_title_dropdown.scss b/ui/scss/core/components/_sim_title_dropdown.scss index cd4c2303fd..2fd95adaa0 100644 --- a/ui/scss/core/components/_sim_title_dropdown.scss +++ b/ui/scss/core/components/_sim_title_dropdown.scss @@ -41,25 +41,3 @@ } } } - -@include media-breakpoint-down(xxl) { - .sim-title { - .sim-link { - .sim-link-content { - padding-left: $gap-width-sm * 2; - padding-right: $gap-width-sm * 2; - } - } - } -} - -@include media-breakpoint-down(lg) { - .sim-title { - .sim-link { - .sim-link-content { - padding-left: $gap-width-sm; - padding-right: $gap-width-sm; - } - } - } -} diff --git a/ui/scss/core/components/individual_sim_ui/_gear_tab.scss b/ui/scss/core/components/individual_sim_ui/_gear_tab.scss new file mode 100644 index 0000000000..4dca18c186 --- /dev/null +++ b/ui/scss/core/components/individual_sim_ui/_gear_tab.scss @@ -0,0 +1,7 @@ +#gear-tab { + .tab-pane-content-container { + .gear-tab-left { + flex-direction: column; + } + } +} diff --git a/ui/scss/core/components/individual_sim_ui/_gem_summary.scss b/ui/scss/core/components/individual_sim_ui/_gem_summary.scss new file mode 100644 index 0000000000..e6821dcfd2 --- /dev/null +++ b/ui/scss/core/components/individual_sim_ui/_gem_summary.scss @@ -0,0 +1,33 @@ +.gem-summary-root { + width: 50%; + + .gem-summary-link { + --gem-width: 2rem; + + display: flex; + align-items: center; + + .gem-icon { + position: unset; + margin-right: map-get($spacers, 1); + border-radius: 0; + border: $border-default; + } + + &:not(:last-child) { + margin-bottom: map-get($spacers, 1); + } + } +} + +@include media-breakpoint-down(xl) { + .gem-summary-root { + margin-bottom: var(--container-padding); + } +} + +@include media-breakpoint-down(md) { + .gem-summary-root { + width: 100%; + } +} \ No newline at end of file diff --git a/ui/scss/core/individual_sim_ui/index.scss b/ui/scss/core/individual_sim_ui/index.scss index 745ca46e06..92330b1c17 100644 --- a/ui/scss/core/individual_sim_ui/index.scss +++ b/ui/scss/core/individual_sim_ui/index.scss @@ -26,9 +26,11 @@ @import "../components/stat_weights_action"; @import "../components/unit_picker"; +@import "../components/individual_sim_ui/gear_tab"; @import "../components/individual_sim_ui/settings_tab"; @import "../components/individual_sim_ui/rotation_tab"; @import "../components/individual_sim_ui/talents_tab"; +@import "../components/individual_sim_ui/gem_summary"; @import "../talents/hunter_pet"; @import "../talents/glyphs_picker"; diff --git a/ui/scss/core/sim_ui/_shared.scss b/ui/scss/core/sim_ui/_shared.scss index 5756ec77e1..0f63e75344 100644 --- a/ui/scss/core/sim_ui/_shared.scss +++ b/ui/scss/core/sim_ui/_shared.scss @@ -111,20 +111,6 @@ td, th { width: 100%; min-height: unset; } - - .sim-content { - padding-left: $gap-width-sm; - padding-right: $gap-width-sm; - } - } - } -} - -@include media-breakpoint-down(sm) { - .sim-ui { - .sim-content { - padding-left: $gap-width-sm; - padding-right: $gap-width-sm; } } } diff --git a/ui/scss/core/sim_ui/_sidebar.scss b/ui/scss/core/sim_ui/_sidebar.scss index 1fd7f367ab..4a1a1a1eb4 100644 --- a/ui/scss/core/sim_ui/_sidebar.scss +++ b/ui/scss/core/sim_ui/_sidebar.scss @@ -59,9 +59,6 @@ @include media-breakpoint-down(xxl) { .sim-sidebar { .sim-sidebar-content { - padding-left: $gap-width-sm * 2; - padding-right: $gap-width-sm * 2; - .sim-sidebar-actions { padding: 0; margin: 0; diff --git a/ui/scss/shared/_gems.scss b/ui/scss/shared/_gems.scss index 014b69e73f..2e9c50d880 100644 --- a/ui/scss/shared/_gems.scss +++ b/ui/scss/shared/_gems.scss @@ -9,21 +9,24 @@ margin-right: 1px; } - .gem-icon { - @include wowhead-background-icon; - position: absolute; - width: calc(4 * var(--gem-width) / 5); - height: calc(4 * var(--gem-width) / 5); - inset: calc(var(--gem-width) / 10); - border-radius: 100%; - z-index: 1; - } - + .gem-icon, .socket-icon { - @include wowhead-background-icon; position: absolute; - width: 100%; - height: 100%; - inset: 0; } } + +.gem-icon { + @include wowhead-background-icon; + width: calc(4 * var(--gem-width) / 5); + height: calc(4 * var(--gem-width) / 5); + inset: calc(var(--gem-width) / 10); + border-radius: 100%; + z-index: 1; +} + +.socket-icon { + @include wowhead-background-icon; + width: 100%; + height: 100%; + inset: 0; +} diff --git a/ui/scss/shared/_global.scss b/ui/scss/shared/_global.scss index 0336e29e90..ea16ef14f9 100644 --- a/ui/scss/shared/_global.scss +++ b/ui/scss/shared/_global.scss @@ -2,7 +2,7 @@ :root { --bs-body-font-size: 14px; - --container-padding: #{$gap-width-sm}; + --container-padding: #{$gap-width}; font-size: var(--bs-body-font-size); }