From 0ad4c8d71e1972ec588bdf2057c3ef5b901d4d30 Mon Sep 17 00:00:00 2001 From: Joaquin Pereyra Date: Wed, 2 Jul 2025 21:49:46 -0300 Subject: [PATCH] FEAT: add filters getters on FilterMenu class --- module/applications/sheets/character.mjs | 20 +----- module/applications/ux/filter-menu.mjs | 87 +++++++++++++++++++++++- module/config/itemConfig.mjs | 4 -- styles/daggerheart.css | 12 ++-- styles/less/global/filter-menu.less | 50 +++++++------- 5 files changed, 122 insertions(+), 51 deletions(-) diff --git a/module/applications/sheets/character.mjs b/module/applications/sheets/character.mjs index c3833935..f86cdc34 100644 --- a/module/applications/sheets/character.mjs +++ b/module/applications/sheets/character.mjs @@ -571,23 +571,7 @@ export default class CharacterSheet extends DaggerheartSheet(ActorSheetV2) { content: '.items-section', callback: this._onMenuFilterInventory.bind(this), target: '.filter-button', - filters: [{ - group: "Type", - name: "Weapons", - filter: { - field: "type", - operator: foundry.applications.ux.SearchFilter.OPERATORS.EQUALS, - value: "weapon", - } - }, { - group: "Type", - name: "Armor", - filter: { - field: "type", - operator: foundry.applications.ux.SearchFilter.OPERATORS.EQUALS, - value: "armor", - } - }], + filters: FilterMenu.invetoryFilters, }, { key: 'loadout', @@ -595,7 +579,7 @@ export default class CharacterSheet extends DaggerheartSheet(ActorSheetV2) { content: '.items-section', callback: this._onMenuFilterLoadout.bind(this), target: '.filter-button', - filters: [], + filters: FilterMenu.cardsFilters, } ]; diff --git a/module/applications/ux/filter-menu.mjs b/module/applications/ux/filter-menu.mjs index ba7f3e1e..4052cf18 100644 --- a/module/applications/ux/filter-menu.mjs +++ b/module/applications/ux/filter-menu.mjs @@ -50,7 +50,7 @@ export default class FilterMenu extends foundry.applications.ux.ContextMenu { await super.render(target, { ...options, animate: false }); // Create menu structure - const menu = document.createElement("div"); + const menu = document.createElement("menu"); menu.className = "filter-menu"; // Group items by their group property @@ -158,4 +158,87 @@ export default class FilterMenu extends foundry.applications.ux.ContextMenu { this.callback(event, this.contentElement, filters); } -} \ No newline at end of file + + /** + * Generate and return a sorted array of inventory filters. + * @returns {Array} An array of filter objects, sorted by name within each group. + */ + static get invetoryFilters() { + const { OPERATORS } = foundry.applications.ux.SearchFilter; + + const typesFilters = Object.entries(CONFIG.Item.dataModels) + .filter(([, { metadata }]) => metadata.isInventoryItem) + .map(([type, { metadata }]) => ({ + group: game.i18n.localize("Type"), + name: game.i18n.localize(metadata.label), + filter: { + field: "type", + operator: OPERATORS.EQUALS, + value: type + } + })); + + const burdenFilter = Object.values(CONFIG.daggerheart.GENERAL.burden).map(({ value, label }) => ({ + group: game.i18n.localize("DAGGERHEART.Sheets.Weapon.Burden"), + name: game.i18n.localize(label), + filter: { + field: "system.burden", + operator: OPERATORS.EQUALS, + value: value + } + })); + + const damageTypeFilter = Object.values(CONFIG.daggerheart.GENERAL.damageTypes).map(({ id, abbreviation }) => ({ + group: "Damage Type", //TODO localize + name: game.i18n.localize(abbreviation), + filter: { + field: "system.damage.type", + operator: OPERATORS.EQUALS, + value: id + } + })); + + + return [ + ...game.i18n.sortObjects(typesFilters, "name"), + ...game.i18n.sortObjects(burdenFilter, "name"), + ...game.i18n.sortObjects(damageTypeFilter, "name"), + ]; + } + + /** + * Generate and return a sorted array of inventory filters. + * @returns {Array} An array of filter objects, sorted by name within each group. + */ + static get cardsFilters() { + const { OPERATORS } = foundry.applications.ux.SearchFilter; + + const typesFilters = Object.values(CONFIG.daggerheart.DOMAIN.cardTypes) + .map(({ id, label }) => ({ + group: game.i18n.localize("Type"), + name: game.i18n.localize(label), + filter: { + field: "system.type", + operator: OPERATORS.EQUALS, + value: id + } + })); + + const domainFilter = Object.values(CONFIG.daggerheart.DOMAIN.domains).map(({id, label}) => ({ + group: game.i18n.localize("DAGGERHEART.Sheets.DomainCard.Domain"), + name: game.i18n.localize(label), + filter: { + field: "system.domain", + operator: OPERATORS.EQUALS, + value: id + } + })) + + const sort = (arr) => game.i18n.sortObjects(arr, "name"); + + return [ + ...sort(typesFilters), + ...sort(domainFilter), + ]; + } +} diff --git a/module/config/itemConfig.mjs b/module/config/itemConfig.mjs index 47af716b..a2a786b9 100644 --- a/module/config/itemConfig.mjs +++ b/module/config/itemConfig.mjs @@ -723,7 +723,3 @@ export const actionTypes = { label: 'DAGGERHEART.ActionType.Reaction' } }; - -export const invetoryFilters = [ - -]; \ No newline at end of file diff --git a/styles/daggerheart.css b/styles/daggerheart.css index f81a334c..7555ae44 100755 --- a/styles/daggerheart.css +++ b/styles/daggerheart.css @@ -5208,24 +5208,28 @@ div.daggerheart.views.multiclass { font-family: 'Montserrat', sans-serif; font-weight: bold; color: light-dark(#18162e, #f3c267); + font-size: var(--font-size-12); } -.filter-buttons { +.filter-menu fieldset.filter-section .filter-buttons { display: flex; flex-wrap: wrap; + justify-content: space-evenly; gap: 5px; } -.filter-buttons button { +.filter-menu fieldset.filter-section .filter-buttons button { background: light-dark(rgba(0, 0, 0, 0.3), #18162e); color: light-dark(#18162e, #f3c267); outline: none; box-shadow: none; border: 1px solid light-dark(#18162e, #18162e); + padding: 0 0.2rem; + font-size: var(--font-size-12); } -.filter-buttons button:hover { +.filter-menu fieldset.filter-section .filter-buttons button:hover { background: light-dark(transparent, #f3c267); color: light-dark(#18162e, #18162e); } -.filter-buttons button.active { +.filter-menu fieldset.filter-section .filter-buttons button.active { animation: glow 0.75s infinite alternate; } .daggerheart { diff --git a/styles/less/global/filter-menu.less b/styles/less/global/filter-menu.less index 0680bd21..09962afb 100644 --- a/styles/less/global/filter-menu.less +++ b/styles/less/global/filter-menu.less @@ -15,29 +15,33 @@ font-family: @font-body; font-weight: bold; color: light-dark(@dark-blue, @golden); - } - } -} - -.filter-buttons { - display: flex; - flex-wrap: wrap; - gap: 5px; - - button { - background: light-dark(@light-black, @dark-blue); - color: light-dark(@dark-blue, @golden); - outline: none; - box-shadow: none; - border: 1px solid light-dark(@dark-blue, @dark-blue); - - &:hover { - background: light-dark(transparent, @golden); - color: light-dark(@dark-blue, @dark-blue); - } - - &.active { - animation: glow 0.75s infinite alternate; + font-size: var(--font-size-12); + } + + .filter-buttons { + display: flex; + flex-wrap: wrap; + justify-content: space-evenly; + gap: 5px; + + button { + background: light-dark(@light-black, @dark-blue); + color: light-dark(@dark-blue, @golden); + outline: none; + box-shadow: none; + border: 1px solid light-dark(@dark-blue, @dark-blue); + padding: 0 0.2rem; + font-size: var(--font-size-12); + + &:hover { + background: light-dark(transparent, @golden); + color: light-dark(@dark-blue, @dark-blue); + } + + &.active { + animation: glow 0.75s infinite alternate; + } + } } } }