Skip to content

Commit

Permalink
Merge pull request #16 from fhmurakami/feat/report
Browse files Browse the repository at this point in the history
It  introduces a new feature to generate reports that compile the answers from a group of participants for a specific set of equations, providing a comprehensive overview of their responses
  • Loading branch information
fhmurakami authored Dec 29, 2024
2 parents 989e805 + 28f97a0 commit d5e0fe2
Show file tree
Hide file tree
Showing 31 changed files with 622 additions and 26 deletions.
17 changes: 13 additions & 4 deletions app/assets/stylesheets/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,10 @@ li {
margin-top: 1rem;
}

.pr-9 {
padding-right: 9rem;
}

.text-center {
text-align: center;
}
Expand Down Expand Up @@ -248,7 +252,8 @@ nav div.user {
.buttons .collections,
.buttons .equations,
.buttons .groupings,
.buttons .participants {
.buttons .participants,
.buttons .reports {
width: 100%;
gap: 2.5vmin;
}
Expand Down Expand Up @@ -326,7 +331,8 @@ nav div.user {
.collections,
.equations,
.groupings,
.participants {
.participants,
.reports {
width: 90%;
display: flex;
flex-direction: column;
Expand Down Expand Up @@ -363,7 +369,8 @@ nav div.user {

#answers,
#collections,
#groupings {
#groupings,
#reports {
width: 100%;
display: flex;
flex-direction: column;
Expand Down Expand Up @@ -427,7 +434,8 @@ nav div.user {
.collections a,
.equations a,
.groupings a,
.participants a {
.participants a,
.reports a {
text-align: center;
font-size: 1.5rem;
margin: 2vmin auto;
Expand Down Expand Up @@ -525,6 +533,7 @@ a.forgot-password:hover {
}

.btn {
/* font-size: 1.2rem; */
cursor: pointer;
width: 100%;
text-align: center;
Expand Down
38 changes: 38 additions & 0 deletions app/controllers/reports_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
class ReportsController < ApplicationController
before_action :set_report, only: %i[ show destroy ]

# GET /reports or /reports.json
def index
@reports = current_admin.reports
end

# GET /reports/1 or /reports/1.json
def show
if @report.nil?
@reports = current_admin.reports
flash.now[:alert] = I18n.t("reports.errors.not_found")
render :index
end
end

# DELETE /reports/1 or /reports/1.json
def destroy
@report.destroy!

respond_to do |format|
format.html { redirect_to reports_path, status: :see_other, notice: I18n.t("reports.destroyed") }
format.json { head :no_content }
end
end

private
# Use callbacks to share common setup or constraints between actions.
def set_report
@report = Report.find_by_id(params[:id])
end

# Only allow a list of trusted parameters through.
def report_params
params.require(:report).permit(:user_admin_id, :collection_id, :grouping_id)
end
end
1 change: 1 addition & 0 deletions app/models/collection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ class Collection < ApplicationRecord
belongs_to :user_admin, class_name: "User::Admin", dependent: :destroy
has_many :collection_equations, dependent: :destroy
has_many :equations, through: :collection_equations
has_many :reports

validates :name, :equations_quantity, presence: true
end
9 changes: 9 additions & 0 deletions app/models/report.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class Report < ApplicationRecord
belongs_to :user_admin, class_name: "User::Admin", foreign_key: "user_admin_id"
belongs_to :collection
belongs_to :grouping

has_many :participants, class_name: "User::Participant",
foreign_key: :user_participant_id, through: :grouping
has_many :rounds
end
28 changes: 28 additions & 0 deletions app/models/round.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,33 @@
class Round < ApplicationRecord
belongs_to :collection
belongs_to :participant, class_name: "User::Participant", foreign_key: "user_participant_id"
belongs_to :report, optional: true

has_many :answers

validates :user_participant_id, uniqueness: { scope: :collection_id }
validate :rounds_length

private

def rounds_length
report = Report.find_by(collection: collection)
grouping = report&.grouping

if report && grouping
rounds = report&.rounds
participants = grouping&.participants

if rounds && participants
return true if rounds.length <= participants.length

errors.add(
:base,
:too_many_rounds,
grouping: grouping.name,
count: grouping.participants.length
)
end
end
end
end
23 changes: 23 additions & 0 deletions app/services/report/create_service.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
class Report::CreateService
def initialize(user_admin, collection, grouping)
@user_admin = user_admin
@collection = collection
@grouping = grouping
end

def self.call(user_admin:, collection:, grouping:)
new(user_admin, collection, grouping).call
end

def call
create_report
end

def create_report
@report = Report.find_or_create_by(
user_admin: @user_admin,
collection: @collection,
grouping: @grouping
)
end
end
10 changes: 9 additions & 1 deletion app/services/round/finish_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,17 @@ def collection_completed?
def finalize_round
@completed_at = Time.current

report = Report::CreateService.call(
user_admin: @user_admin,
collection: @collection,
grouping: @participant.grouping,
)

@current_round.update!(
completed_at: @completed_at,
round_time: calculate_round_time
round_time: calculate_round_time,
report: report

)
end

Expand Down
54 changes: 54 additions & 0 deletions app/views/reports/_report.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<div id="<%= dom_id report %>">
<table>
<thead>
<tr>
<th colspan="10">
<strong><%= report.grouping.name %></strong>
</th>
</tr>
<tr>
<th><strong><%= t("activerecord.models.collection") %></strong></th>
<th colspan="9" class="pr-9"><%= report.collection.name %></th>
</tr>
</thead>
<% report.rounds.each do |round| %>
<thead>
<tr>
<th><strong><%= t("activerecord.models.user/participant") %></strong></th>
<th colspan="9" class="pr-9"><%= round.participant.full_name %></th>
</tr>
</thead>
<tbody>
<tr>
<th rowspan="<%= round.collection.equations.size + 1 %>">
<strong><%= t("activerecord.models.equation").pluralize %></strong>
</th>
<th><%= t("activerecord.attributes.equation.position_a") %></th>
<th><%= t("activerecord.attributes.equation.operator") %></th>
<th><%= t("activerecord.attributes.equation.position_b") %></th>
<th><%= t("activerecord.attributes.equation.position_c") %></th>
<th><%= t("activerecord.attributes.equation.unknown_position") %></th>
<th rowspan="<%= round.collection.equations.size + 1 %>">
<strong><%= t("activerecord.models.answer").pluralize %></strong>
</th>
<th><%= t("activerecord.attributes.answer.answer_value") %></th>
<th><%= t("activerecord.attributes.answer.correct_answer") %></th>
<th><%= t("activerecord.attributes.answer.time") %></th>
</tr>
<% round.answers.each do |answer| %>
<tr>
<td><%= answer.equation.position_a %></td>
<td><%= answer.equation.operator %></td>
<td><%= answer.equation.position_b %></td>
<td><%= answer.equation.position_c %></td>
<td><%= answer.equation.unknown_position %></td>
<td><%= answer.answer_value %></td>
<td><%= answer.correct_answer ? "✔️" : "❌" %></td>
<td><%= answer.formatted_time %></td>
</tr>
<% end %>
<% end %>
</tbody>
<tfoot></tfoot>
</table>
</div>
2 changes: 2 additions & 0 deletions app/views/reports/_report.json.jbuilder
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
json.extract! report, :id, :user_admin_id, :user_participant_id, :collection_id, :grouping_id, :created_at, :updated_at
json.url report_url(report, format: :json)
18 changes: 18 additions & 0 deletions app/views/reports/index.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<% content_for :title, t("activerecord.models.report").pluralize %>
<main class="background">
<section class="blur">
<%= render "shared/header" %>
<h2><%= t("activerecord.models.report").pluralize %></h2>
<div class="reports">
<div id="reports">
<% @reports.each do |report| %>
<div class="card report">
<%= render report %>
<%= link_to t("reports.show"), report %>
</div>
<% end %>
</div>
<%= link_to t("home.back"), root_path, class: "btn mustard btn-text-black" %>
</div>
</section>
</main>
1 change: 1 addition & 0 deletions app/views/reports/index.json.jbuilder
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
json.array! @reports, partial: "reports/report", as: :report
12 changes: 12 additions & 0 deletions app/views/reports/show.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<main class="background">
<section class="blur">
<%= render "shared/header" %>
<div class="panel report">
<%= render @report %>
<div class="actions">
<%= link_to t("reports.back"), reports_path %>
<%= button_to t("reports.delete"), @report, class: "btn crimson", method: :delete, data: { turbo_method: :delete } %>
</div>
</div>
</section>
</main>
1 change: 1 addition & 0 deletions app/views/reports/show.json.jbuilder
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
json.partial! "reports/report", report: @report
2 changes: 1 addition & 1 deletion app/views/shared/_header.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<%= link_to t("activerecord.models.grouping").pluralize, groupings_path, class: "nav-item" %>
<%= link_to t("activerecord.models.collection").pluralize, collections_path, class: "nav-item" %>
<%= link_to t("activerecord.models.equation").pluralize, equations_path, class: "nav-item" %>
<%#= link_to t("activerecord.models.answer").pluralize, answers_path, class: "nav-item" %>
<%= link_to t("activerecord.models.report").pluralize, reports_path, class: "nav-item" %>
<% end %>
</div>
<div class="right">
Expand Down
42 changes: 27 additions & 15 deletions config/locales/pt-BR.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ pt-BR:
register: "Cadastrar nova resposta"
show: "Ver resposta"
show_all: "Ver todas as respostas"
created: "A resposta foi criada com sucesso."
updated: "A resposta foi atualizada com sucesso."
destroyed: "A resposta foi excluída com sucesso."
created: "A resposta foi criada com sucesso!"
updated: "A resposta foi atualizada com sucesso!"
destroyed: "A resposta foi excluída com sucesso!"
collections:
back: "Voltar para etapas"
delete: "Excluir etapa"
Expand All @@ -26,9 +26,9 @@ pt-BR:
register: "Cadastrar nova etapa"
show: "Ver etapa"
show_all: "Ver todas as etapas"
created: "A etapa foi criada com sucesso."
updated: "A etapa foi atualizada com sucesso."
destroyed: "A etapa foi excluída com sucesso."
created: "A etapa foi criada com sucesso!"
updated: "A etapa foi atualizada com sucesso!"
destroyed: "A etapa foi excluída com sucesso!"
errors:
equations_limit:
one: "não pode ter mais do que %{count} equação"
Expand All @@ -44,9 +44,9 @@ pt-BR:
register: "Cadastrar equação"
show: "Ver equação"
show_all: "Ver todas as equações"
created: "A equação foi criada com sucesso."
updated: "A equação foi atualizada com sucesso."
destroyed: "A equação foi excluída com sucesso."
created: "A equação foi criada com sucesso!"
updated: "A equação foi atualizada com sucesso!"
destroyed: "A equação foi excluída com sucesso!"
groupings:
back: "Voltar para grupos"
delete: "Excluir grupo"
Expand All @@ -56,9 +56,9 @@ pt-BR:
select: "Selecionar grupo"
show: "Ver grupo"
show_all: "Ver todos os grupos"
created: "O grupo foi criado com sucesso."
updated: "O grupo foi atualizado com sucesso."
destroyed: "O grupo foi excluído com sucesso."
created: "O grupo foi criado com sucesso!"
updated: "O grupo foi atualizado com sucesso!"
destroyed: "O grupo foi excluído com sucesso!"
participants:
back: "Voltar para participantes"
delete: "Excluir participante"
Expand All @@ -70,9 +70,17 @@ pt-BR:
register: "Cadastrar participante"
show: "Ver participante"
show_all: "Ver todos os participantes"
created: "O participante foi criado com sucesso."
updated: "O participante foi atualizado com sucesso."
destroyed: "O participante foi excluído com sucesso."
created: "O participante foi criado com sucesso!"
updated: "O participante foi atualizado com sucesso!"
destroyed: "O participante foi excluído com sucesso!"
reports:
back: "Voltar para relatórios"
delete: "Excluir relatório"
show: "Ver relatório"
show_all: "Ver todos os relatórios"
destroyed: "O relatório foi excluído com sucesso!"
errors:
not_found: "O relatório não foi encontrado!"
rounds:
new: "Nova sessão"
congrats: "Parabéns!"
Expand Down Expand Up @@ -112,6 +120,7 @@ pt-BR:
collection: "Etapa"
equation: "Equação"
grouping: "Grupo"
report: "Relatório"
round: "Sessão"
user/admin: "Admin"
user/participant: "Participante"
Expand Down Expand Up @@ -256,6 +265,9 @@ pt-BR:
wrong_length:
one: não possui o tamanho esperado (%{count} caracter)
other: não possui o tamanho esperado (%{count} caracteres)
too_many_rounds:
one: "%{model} não pode ter mais que %{count} sessão, pois o Grupo %{grouping} possui apenas %{count} participante"
other: "%{model} não pode ter mais que %{count} sessões, pois o Grupo %{grouping} possui apenas %{count} participantes"
template:
body: "Por favor, verifique o(s) seguinte(s) campo(s):"
header:
Expand Down
Loading

0 comments on commit d5e0fe2

Please sign in to comment.