add filter support to crew members endpoint

GET /crew/members now accepts ?filter param:
- active (default): active members only
- retired: retired members only
- phantom: phantom players only
- all: all members + phantoms

Response includes both members[] and phantoms[] arrays.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Justin Edmund 2025-12-04 00:07:22 -08:00
parent 4c8f4ffcf3
commit 50e2318f59
2 changed files with 76 additions and 12 deletions

View file

@ -41,9 +41,33 @@ module Api
end
# GET /crew/members
# Params:
# filter: 'active' (default), 'retired', 'phantom', 'all'
def members
members = @crew.active_memberships.includes(:user).order(role: :desc, created_at: :asc)
render json: CrewMembershipBlueprint.render(members, view: :with_user, root: :members)
filter = params[:filter]&.to_sym || :active
case filter
when :active
members = @crew.active_memberships.includes(:user).order(role: :desc, created_at: :asc)
phantoms = []
when :retired
members = @crew.crew_memberships.retired.includes(:user).order(retired_at: :desc)
phantoms = []
when :phantom
members = []
phantoms = @crew.phantom_players.includes(:claimed_by).order(:name)
when :all
members = @crew.crew_memberships.includes(:user).order(role: :desc, retired: :asc, created_at: :asc)
phantoms = @crew.phantom_players.includes(:claimed_by).order(:name)
else
members = @crew.active_memberships.includes(:user).order(role: :desc, created_at: :asc)
phantoms = []
end
render json: {
members: CrewMembershipBlueprint.render_as_hash(members, view: :with_user),
phantoms: PhantomPlayerBlueprint.render_as_hash(phantoms, view: :with_claimed_by)
}
end
# POST /crew/leave

View file

@ -121,19 +121,59 @@ RSpec.describe 'Api::V1::Crews', type: :request do
let!(:captain_membership) { create(:crew_membership, crew: crew, user: user, role: :captain) }
let!(:member1) { create(:crew_membership, crew: crew, role: :member) }
let!(:member2) { create(:crew_membership, crew: crew, role: :vice_captain) }
let!(:phantom1) { create(:phantom_player, crew: crew, name: 'Phantom A') }
it 'returns all active crew members' do
get '/api/v1/crew/members', headers: auth_headers
expect(response).to have_http_status(:ok)
json = JSON.parse(response.body)
expect(json['members'].length).to eq(3)
context 'with default filter (active)' do
it 'returns all active crew members' do
get '/api/v1/crew/members', headers: auth_headers
expect(response).to have_http_status(:ok)
json = JSON.parse(response.body)
expect(json['members'].length).to eq(3)
expect(json['phantoms']).to eq([])
end
it 'excludes retired members' do
member1.retire!
get '/api/v1/crew/members', headers: auth_headers
json = JSON.parse(response.body)
expect(json['members'].length).to eq(2)
end
end
it 'excludes retired members' do
member1.retire!
get '/api/v1/crew/members', headers: auth_headers
json = JSON.parse(response.body)
expect(json['members'].length).to eq(2)
context 'with filter=retired' do
before { member1.retire! }
it 'returns only retired members' do
get '/api/v1/crew/members', params: { filter: 'retired' }, headers: auth_headers
expect(response).to have_http_status(:ok)
json = JSON.parse(response.body)
expect(json['members'].length).to eq(1)
expect(json['members'][0]['retired']).to be true
expect(json['phantoms']).to eq([])
end
end
context 'with filter=phantom' do
it 'returns only phantom players' do
get '/api/v1/crew/members', params: { filter: 'phantom' }, headers: auth_headers
expect(response).to have_http_status(:ok)
json = JSON.parse(response.body)
expect(json['members']).to eq([])
expect(json['phantoms'].length).to eq(1)
expect(json['phantoms'][0]['name']).to eq('Phantom A')
end
end
context 'with filter=all' do
before { member1.retire! }
it 'returns all members and phantoms' do
get '/api/v1/crew/members', params: { filter: 'all' }, headers: auth_headers
expect(response).to have_http_status(:ok)
json = JSON.parse(response.body)
expect(json['members'].length).to eq(3) # includes retired
expect(json['phantoms'].length).to eq(1)
end
end
end