Skip to content

Commit 6cf7017

Browse files
graylikemeclaude
andcommitted
refactor: change factionType filter to accept multiple values
Rename to factionTypes (plural) and accept a list so roster builders can filter by multiple faction classifications at once, e.g. factionTypes: [GREAT_HOUSE, PERIPHERY]. Uses IN() instead of = in the availability subquery. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent dadcb98 commit 6cf7017

File tree

2 files changed

+17
-8
lines changed

2 files changed

+17
-8
lines changed

crates/api/src/db/units.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ pub struct UnitFilter<'a> {
4949
pub bv_min: Option<i32>,
5050
pub bv_max: Option<i32>,
5151
pub faction_slug: Option<&'a str>,
52-
pub faction_type: Option<&'a str>,
52+
pub faction_types: &'a [&'a str],
5353
pub era_slug: Option<&'a str>,
5454
pub is_omnimech: Option<bool>,
5555
pub config: Option<&'a str>,
@@ -131,13 +131,16 @@ pub async fn search(
131131
builder.push_bind(faction);
132132
builder.push(")");
133133
}
134-
if let Some(ft) = filter.faction_type {
134+
if !filter.faction_types.is_empty() {
135135
builder.push(r#" AND EXISTS (
136136
SELECT 1 FROM unit_availability ua
137137
JOIN factions f2 ON f2.id = ua.faction_id
138-
WHERE ua.unit_id = u.id AND f2.faction_type = "#);
139-
builder.push_bind(ft);
140-
builder.push(")");
138+
WHERE ua.unit_id = u.id AND f2.faction_type IN ("#);
139+
let mut sep = builder.separated(", ");
140+
for ft in filter.faction_types {
141+
sep.push_bind(*ft);
142+
}
143+
builder.push("))");
141144
}
142145
if let Some(era) = filter.era_slug {
143146
builder.push(r#" AND EXISTS (
@@ -373,7 +376,7 @@ mod tests {
373376
bv_min: None,
374377
bv_max: None,
375378
faction_slug: None,
376-
faction_type: None,
379+
faction_types: &[],
377380
era_slug: None,
378381
is_omnimech: None,
379382
config: None,

crates/api/src/graphql/query.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ impl QueryRoot {
148148
#[graphql(desc = "Minimum Battle Value filter (inclusive).")] bv_min: Option<i32>,
149149
#[graphql(desc = "Maximum Battle Value filter (inclusive).")] bv_max: Option<i32>,
150150
#[graphql(desc = "Filter to units available to this faction. Lowercase, hyphen-separated slug (e.g. \"clan-wolf\").")] faction_slug: Option<String>,
151-
#[graphql(desc = "Filter to units available to any faction of this type.")] faction_type: Option<FactionTypeFilter>,
151+
#[graphql(desc = "Filter to units available to any faction of these types. Accepts multiple values.")] faction_types: Option<Vec<FactionTypeFilter>>,
152152
#[graphql(desc = "Filter to units available in this era.")] era_slug: Option<EraFilter>,
153153
#[graphql(desc = "Filter to OmniMechs only (true) or non-OmniMechs (false).")] is_omnimech: Option<bool>,
154154
#[graphql(desc = "Filter by chassis config. One of: Biped, Quad, Tripod, LAM.")] config: Option<String>,
@@ -161,6 +161,12 @@ impl QueryRoot {
161161
let first = first.unwrap_or(20).clamp(1, 100) as i64;
162162
let after_cursor = after.as_deref().and_then(decode_cursor);
163163

164+
let faction_type_strs: Vec<&str> = faction_types
165+
.unwrap_or_default()
166+
.iter()
167+
.map(|f| f.as_db_str())
168+
.collect();
169+
164170
let filter = units::UnitFilter {
165171
name_search: name_search.as_deref(),
166172
tech_base: tech_base.map(|t| t.as_db_str()),
@@ -170,7 +176,7 @@ impl QueryRoot {
170176
bv_min,
171177
bv_max,
172178
faction_slug: faction_slug.as_deref(),
173-
faction_type: faction_type.map(|f| f.as_db_str()),
179+
faction_types: &faction_type_strs,
174180
era_slug: era_slug.map(|e| e.as_db_str()),
175181
is_omnimech,
176182
config: config.as_deref(),

0 commit comments

Comments
 (0)