185 lines
6.3 KiB
Ruby
185 lines
6.3 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module Api
|
|
module V1
|
|
class CrewsController < Api::V1::ApiController
|
|
include CrewAuthorizationConcern
|
|
|
|
before_action :restrict_access
|
|
before_action :set_crew, only: %i[show update members roster leave transfer_captain]
|
|
before_action :require_crew!, only: %i[show update members roster]
|
|
before_action :authorize_crew_member!, only: %i[show members]
|
|
before_action :authorize_crew_officer!, only: %i[update roster]
|
|
before_action :authorize_crew_captain!, only: %i[transfer_captain]
|
|
|
|
# GET /crew or GET /crews/:id
|
|
def show
|
|
render json: CrewBlueprint.render(@crew, view: :full, root: :crew, current_user: current_user)
|
|
end
|
|
|
|
# POST /crews
|
|
def create
|
|
raise CrewErrors::AlreadyInCrewError if current_user.crew.present?
|
|
|
|
@crew = Crew.new(crew_params)
|
|
|
|
ActiveRecord::Base.transaction do
|
|
@crew.save!
|
|
CrewMembership.create!(crew: @crew, user: current_user, role: :captain)
|
|
end
|
|
|
|
render json: CrewBlueprint.render(@crew.reload, view: :full, root: :crew, current_user: current_user), status: :created
|
|
end
|
|
|
|
# PUT /crew
|
|
def update
|
|
if @crew.update(crew_params)
|
|
render json: CrewBlueprint.render(@crew, view: :full, root: :crew, current_user: current_user)
|
|
else
|
|
render_validation_error_response(@crew)
|
|
end
|
|
end
|
|
|
|
# GET /crew/members
|
|
# Params:
|
|
# filter: 'active' (default), 'retired', 'phantom', 'all'
|
|
def members
|
|
filter = params[:filter]&.to_sym || :active
|
|
|
|
case filter
|
|
when :active
|
|
members = @crew.active_memberships.includes(:user).order(role: :desc, created_at: :asc)
|
|
phantoms = @crew.phantom_players.not_deleted.active.includes(:claimed_by).order(:name)
|
|
when :retired
|
|
members = @crew.crew_memberships.retired.includes(:user).order(retired_at: :desc)
|
|
phantoms = @crew.phantom_players.not_deleted.retired.includes(:claimed_by).order(:name)
|
|
when :phantom
|
|
members = []
|
|
phantoms = @crew.phantom_players.not_deleted.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.not_deleted.includes(:claimed_by).order(:name)
|
|
else
|
|
members = @crew.active_memberships.includes(:user).order(role: :desc, created_at: :asc)
|
|
phantoms = @crew.phantom_players.not_deleted.active.includes(:claimed_by).order(:name)
|
|
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
|
|
def leave
|
|
membership = current_user.active_crew_membership
|
|
raise CrewErrors::NotInCrewError unless membership
|
|
raise CrewErrors::CaptainCannotLeaveError if membership.captain?
|
|
|
|
membership.retire!
|
|
head :no_content
|
|
end
|
|
|
|
# GET /crew/roster
|
|
# Returns collection ownership for crew members based on requested item IDs
|
|
# Params: character_ids[], weapon_ids[], summon_ids[]
|
|
def roster
|
|
members = @crew.active_memberships.includes(:user)
|
|
|
|
render json: {
|
|
members: members.map { |m| build_member_roster(m) }
|
|
}
|
|
end
|
|
|
|
# POST /crews/:id/transfer_captain
|
|
def transfer_captain
|
|
new_captain_id = params[:user_id]
|
|
new_captain_membership = @crew.active_memberships.find_by(user_id: new_captain_id)
|
|
|
|
raise CrewErrors::MemberNotFoundError unless new_captain_membership
|
|
|
|
ActiveRecord::Base.transaction do
|
|
current_user.active_crew_membership.update!(role: :vice_captain)
|
|
new_captain_membership.update!(role: :captain)
|
|
end
|
|
|
|
render json: CrewBlueprint.render(@crew.reload, view: :full, root: :crew, current_user: current_user)
|
|
end
|
|
|
|
private
|
|
|
|
def set_crew
|
|
@crew = if params[:id]
|
|
Crew.find(params[:id])
|
|
else
|
|
current_user&.crew
|
|
end
|
|
end
|
|
|
|
def crew_params
|
|
params.require(:crew).permit(:name, :gamertag, :granblue_crew_id, :description)
|
|
end
|
|
|
|
def require_crew!
|
|
render_not_found_response('crew') unless @crew
|
|
end
|
|
|
|
def build_member_roster(membership)
|
|
user = membership.user
|
|
{
|
|
user_id: user.id,
|
|
username: user.username,
|
|
role: membership.role,
|
|
characters: find_collection_items(user, :characters),
|
|
weapons: find_collection_items(user, :weapons),
|
|
summons: find_collection_items(user, :summons)
|
|
}
|
|
end
|
|
|
|
def find_collection_items(user, type)
|
|
ids = params["#{type.to_s.singularize}_ids"]
|
|
return [] if ids.blank?
|
|
|
|
collection = case type
|
|
when :characters then user.collection_characters.includes(:character).where(character_id: ids)
|
|
when :weapons then user.collection_weapons.includes(:weapon).where(weapon_id: ids)
|
|
when :summons then user.collection_summons.includes(:summon).where(summon_id: ids)
|
|
end
|
|
|
|
collection.map do |item|
|
|
canonical = case type
|
|
when :characters then item.character
|
|
when :weapons then item.weapon
|
|
when :summons then item.summon
|
|
end
|
|
|
|
result = {
|
|
id: item_id_for(item, type),
|
|
uncap_level: item.uncap_level,
|
|
transcendence_step: item.transcendence_step,
|
|
flb: canonical&.flb,
|
|
ulb: canonical&.ulb
|
|
}
|
|
|
|
if type == :characters
|
|
result[:special] = canonical&.special
|
|
# For characters, transcendence availability is indicated by ulb on non-special chars
|
|
result[:transcendence] = !canonical&.special && canonical&.ulb
|
|
else
|
|
result[:transcendence] = canonical&.transcendence
|
|
end
|
|
|
|
result
|
|
end
|
|
end
|
|
|
|
def item_id_for(item, type)
|
|
case type
|
|
when :characters then item.character_id
|
|
when :weapons then item.weapon_id
|
|
when :summons then item.summon_id
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|