Add Overall Response Rate

This commit is contained in:
rebuilt 2023-05-16 13:19:29 -07:00
parent bb6d31ecf1
commit a785c69c44
14 changed files with 920 additions and 450 deletions

View file

@ -89,6 +89,26 @@
width: 20px;
}
.overall-response-rate-row {
width: 55%;
display: flex;
flex-direction: row;
justify-content: space-between;
margin-top: -23px;
}
.overall-response-rate-container {
padding: 0.4em 0.7em;
width: 48%;
display: flex;
justify-content: space-between;
align-items: center;
color: $gray-1;
@extend .bg-color-gray-3;
@extend .border-radius-8;
@extend .font-size-14
}
@media only screen and (min-width: 768px){
.measure-row-label {
width: 170px;

View file

@ -7,6 +7,10 @@ class OverviewController < SqmApplicationController
def index
@variance_chart_row_presenters = measures.map(&method(:presenter_for_measure))
@category_presenters = Category.sorted.map { |category| CategoryPresenter.new(category:) }
@student_response_rate_presenter = ResponseRatePresenter.new(focus: :student, school: @school,
academic_year: @academic_year)
@teacher_response_rate_presenter = ResponseRatePresenter.new(focus: :teacher, school: @school,
academic_year: @academic_year)
end
private

View file

@ -0,0 +1,45 @@
class ResponseRatePresenter
attr_reader :focus, :academic_year, :school, :survey_items
def initialize(focus:, academic_year:, school:)
@focus = focus
@academic_year = academic_year
@school = school
@survey_items = SurveyItem.student_survey_items if focus == :student
@survey_items = SurveyItem.teacher_survey_items if focus == :teacher
end
def date
SurveyItemResponse.where(survey_item: survey_items, school:).order(updated_at: :DESC).first&.updated_at || Date.new
end
def percentage
cap_at_100(actual_count.to_f / respondents_count.to_f * 100).round
end
def color
# Problem: the color (either $gold or $purple) is determined by the scss variable, but the
# percentage is decided by the presenter. Therefore the class style must be generated
# within this file and not the scss file.
# TODO: Fix this.
percentage > 75 ? "#49416D" : "#FFC857"
end
private
def cap_at_100(value)
value > 100 ? 100 : value
end
def actual_count
SurveyItemResponse.where(school:, academic_year:,
survey_item: survey_items).select(:response_id).distinct.count
end
def respondents_count
respondents = Respondent.find_by(school:, academic_year:)
count = respondents.total_students if focus == :student
count = respondents.total_teachers if focus == :teacher
count
end
end

View file

@ -68,7 +68,7 @@ class SurveyResponsesDataLoader
likert_score = row.likert_score(survey_item_id: survey_item.survey_item_id) || next
unless likert_score.valid_likert_score?
puts "Response ID: #{row.response_id}, Likert score: #{likert_score} rejected" unless likert_score == 'NA'
puts "Response ID: #{row.response_id}, Likert score: #{likert_score} rejected" unless likert_score == "NA"
next
end
response = row.survey_item_response(survey_item:)
@ -96,7 +96,7 @@ class SurveyResponsesDataLoader
def self.get_survey_item_ids_from_headers(headers:)
CSV.parse(headers).first
.filter(&:present?)
.filter { |header| header.start_with? 't-', 's-' }
.filter { |header| header.start_with? "t-", "s-" }
end
private_class_method :process_row

View file

@ -0,0 +1,8 @@
<div class="overall-response-rate-container">
<div>Response Rates as of <%= response_rate_presenter.date.to_date.strftime("%m/%d/%y") %> </div>
<div style="display: flex; justify-content:space-between; width: 100px;">
<div><%= response_rate_presenter.focus.capitalize %> </div>
<%= render partial: "response_rate_graphic", locals: {response_rate_presenter: response_rate_presenter}, cached: true %>
<div><%= response_rate_presenter.percentage %>% </div>
</div>
</div>

View file

@ -0,0 +1,35 @@
<style>
/*
For some reason, none of the sizing in the pie class works, and it always
fills 100% of the containing frame, so the size has to be dictated by .prog
*/
.prog {
width: 16px;
height: 16px;
position: relative;
border: 1px solid black;
border-radius: 50%;
margin-top: 0.2em;
}
.pie {
aspect-ratio: 1;
display: inline-grid;
place-content: center;
margin: 5px;
font-size: 25px;
font-weight: bold;
font-family: sans-serif;
}
#response-rate-pie-<%= response_rate_presenter.focus %>:before{
content: "";
position: absolute;
border-radius: 50%;
inset: 0;
background: conic-gradient(<%= response_rate_presenter.color %> calc(<%= response_rate_presenter.percentage %>*1%),#0000 0);
}
</style>
<div class="prog">
<div id="response-rate-pie-<%= response_rate_presenter.focus %>" class="pie"></div>
</div>

View file

@ -81,6 +81,12 @@
</div>
</div>
<%= render partial: "quality_framework_indicators", locals: { category_presenters: @category_presenters }, cached: true %>
<div class="overall-response-rate-row">
<%= render partial: "response_rate", locals: {response_rate_presenter: @student_response_rate_presenter}, cached: true %>
<%= render partial: "response_rate", locals: {response_rate_presenter: @teacher_response_rate_presenter}, cached: true %>
</div>
</div>
<div class="card">
<h2 class="sub-header-2 mb-4">Distance From Benchmark</h2>