Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EHD-1050: View Report for Year page: Re-build page #592

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
16 changes: 16 additions & 0 deletions GenderPayGap.WebUI/Controllers/ViewReportsController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,21 @@ public IActionResult Employer(long organisationId)
return View("Employer", organisation);
}

[HttpGet("employers/{organisationId}/reporting-year-{reportingYear}")]
public IActionResult ReportForYear(long organisationId, int reportingYear)
{
compareViewService.LoadComparedEmployersFromCookie();

Organisation organisation = ControllerHelper.LoadOrganisationOrThrow404(organisationId, dataRepository);
ControllerHelper.Throw404IfOrganisationIsNotSearchable(organisation);
ControllerHelper.ThrowIfReportingYearIsOutsideOfRange(reportingYear, organisationId, dataRepository);

Return returnForYear = ControllerHelper.LoadReturnForYearOrThrow404(organisation, reportingYear);



return View("ReportForYear", returnForYear);
}

}
}
5 changes: 0 additions & 5 deletions GenderPayGap.WebUI/Controllers/ViewingController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -124,11 +124,6 @@ public IActionResult SuggestEmployerNameJs(string search)
[HttpGet("~/Employer/{employerIdentifier}")]
public IActionResult Employer(string employerIdentifier, int? page = 1)
{
if (string.IsNullOrWhiteSpace(employerIdentifier))
{
return new HttpBadRequestResult("Missing employer identifier");
}

long organisationId = ControllerHelper.DeObfuscateOrganisationIdOrThrow404(employerIdentifier);

return RedirectToAction("Employer", "ViewReports", new {organisationId});
Expand Down
17 changes: 17 additions & 0 deletions GenderPayGap.WebUI/Helpers/ControllerHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,11 @@ public static long DecryptOrganisationIdOrThrow404(string encryptedOrganisationI

public static long DeObfuscateOrganisationIdOrThrow404(string organisationIdentifier)
{
if (string.IsNullOrWhiteSpace(organisationIdentifier))
{
throw new PageNotFoundException();
}

try
{
int organisationId = Obfuscator.DeObfuscate(organisationIdentifier);
Expand Down Expand Up @@ -213,6 +218,18 @@ public static void ThrowIfReportingYearIsOutsideOfRange(int reportingYear, long
}
}

public static Return LoadReturnForYearOrThrow404(Organisation organisation, int reportingYear)
{
Return returnForYear = organisation.GetReturn(reportingYear);

if (returnForYear == null)
{
throw new PageNotFoundException();
}

return returnForYear;
}

public static void ThrowIfAdminIsImpersonatingUser(ClaimsPrincipal aspDotNetUser)
{
if (LoginHelper.IsUserBeingImpersonated(aspDotNetUser))
Expand Down
37 changes: 37 additions & 0 deletions GenderPayGap.WebUI/Helpers/ViewReportsHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System;

namespace GenderPayGap.WebUI.Helpers
{
public static class ViewReportsHelper
{

public static string FormatNumberAsPoundsOrPence(decimal number)
{
if (number >= 1)
{
return $"£{number:#.00}";
}
else
{
return $"{Math.Round(number * 100)}p";
}
}

public static decimal CalculateBarChartHeightForWomen(decimal payGapPercent)
{
return
payGapPercent >= 0
? 100 - payGapPercent
: 100;
}

public static decimal CalculateBarChartHeightForMen(decimal payGapPercent)
{
return
payGapPercent >= 0
? 100
: 10000 / (100 - payGapPercent);
}

}
}
10 changes: 9 additions & 1 deletion GenderPayGap.WebUI/Views/ViewReports/Employer.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,15 @@
<dd class="govuk-summary-list__value employer-reports-page--alight-right-on-desktop govuk-!-padding-top-0">
<a href="@Url.Action("Report", "Viewing", new {employerIdentifier = Model.GetEncryptedId(), year = reportingYear})"
class="govuk-link">
View report
View report (old)
<span class="govuk-visually-hidden">
for reporting year @(ReportingYearsHelper.FormatYearAsReportingPeriod(reportingYear))
</span>
</a>
<br/>
<a href="@Url.Action("ReportForYear", "ViewReports", new {organisationId = Model.OrganisationId, reportingYear = reportingYear})"
class="govuk-link">
View report (new)
<span class="govuk-visually-hidden">
for reporting year @(ReportingYearsHelper.FormatYearAsReportingPeriod(reportingYear))
</span>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
@model GenderPayGap.Database.Return

@{
async Task SmilingFace(bool isFemale, decimal filledPercent)
{
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" class="pay-comparison-quarters-vis-face @(isFemale ? "pay-comparison-quarters-vis-face--woman" : "pay-comparison-quarters-vis-face--man")">
<g>
<circle cx="50" cy="50" r="47" stroke-width="6" class="pay-comparison-quarters-vis-face--face-outline"
style="fill: none;"/>
<rect y="0"
height="100"
x="@(isFemale ? 100 - filledPercent : 0)"
width="@(filledPercent)"
clip-path="circle(47px at @(isFemale ? (filledPercent - 50) : 50)px 50px)"
style="stroke: none;"
class="pay-comparison-quarters-vis-face--face-outline"/>
<rect y="3" x="3" width="94" height="94" rx="0" stroke-width="6" class="pay-comparison-quarters-vis-face--rectangle-outline"
style="fill: none;"/>
<rect y="0"
height="100"
x="@(isFemale ? 100 - filledPercent : 0)"
width="@(filledPercent)"
clip-path="rect(0px @(isFemale ? filledPercent - 100 : 0)px 100px @(isFemale ? filledPercent : 100)px round 0px)"
style="stroke: none;"
class="pay-comparison-quarters-vis-face--rectangle-outline"/>
<circle r="5" cy="35" cx="30" class="pay-comparison-quarters-vis-face--face-feature" style="stroke: none;" />
<circle r="5" cy="35" cx="70" class="pay-comparison-quarters-vis-face--face-feature" style="stroke: none;" />
<line x1="50" x2="50" y1="40" y2="60" stroke-width="5" class="pay-comparison-quarters-vis-face--face-feature" />
<ellipse cx="50" cy="63" rx="25" ry="10" stroke-width="5" class="pay-comparison-quarters-vis-face--face-feature" style="fill: none;"
clip-path="rect(70% 15% 100% 85%)"/>
</g>
</svg>
}

async Task PayComparisonQuartersVisualisationForQuarter(string payQuarterDescription, decimal femalePercent, decimal malePercent, bool bottomBorder)
{
decimal remainderFemale = ((femalePercent / 4) - Math.Floor(femalePercent / 4)) * 100;
decimal remainderMale = ((malePercent / 4) - Math.Floor(malePercent / 4)) * 100;

<div class="pay-comparison-quarters-vis-quarter-explanation">
<div>
In the @(payQuarterDescription):
</div>
<div class="pay-comparison-quarters-vis-quarter-explanation-sides">
<div class="pay-comparison-quarters-vis-quarter-explanation-side pay-comparison-quarters-vis-quarter-explanation-side--left">
@(femalePercent)% women
</div>
<div class="pay-comparison-quarters-vis-quarter-explanation-side pay-comparison-quarters-vis-quarter-explanation-side--right">
@(malePercent)% men
</div>
</div>
</div>
<div class="pay-comparison-quarters-vis-quarter @(bottomBorder ? "pay-comparison-quarters-vis-quarter--bottom-border" : "")">
<div class="pay-comparison-quarters-vis-quarter-side pay-comparison-quarters-vis-quarter-side--left">
<div class="pay-comparison-quarters-vis-quarter-faces pay-comparison-quarters-vis-quarter-faces--women">
@for (int i = 0; i < Math.Floor(femalePercent / 4); i++)
{
await SmilingFace(isFemale: true, filledPercent: 100);
}
@if (remainderFemale > 10)
{
await SmilingFace(isFemale: true, filledPercent: remainderFemale);
}
</div>
</div>
<div class="pay-comparison-quarters-vis-quarter-side pay-comparison-quarters-vis-quarter-side--right">
<div class="pay-comparison-quarters-vis-quarter-faces pay-comparison-quarters-vis-quarter-faces--men">
@for (int i = 0; i < Math.Floor(malePercent / 4); i++)
{
await SmilingFace(isFemale: false, filledPercent: 100);
}
@if (remainderMale > 10)
{
await SmilingFace(isFemale: false, filledPercent: remainderMale);
}
</div>
</div>
</div>
}
}

<figure class="pay-comparison-quarters-vis govuk-body"
aria-hidden="true" @* We use aria-hidden="true" because the content is repeated in the text above *@>
<figcaption class="govuk-visually-hidden">
A visualisation showing the proportions of men and women in each pay quarter of this organisation
</figcaption>
<div id="pay-comparison-quarters-show-rectangles-container" class="govuk-checkboxes govuk-checkboxes--small" data-module="govuk-checkboxes">
<div class="govuk-checkboxes__item" style="float: unset;">
<input class="govuk-checkboxes__input" id="pay-comparison-quarters-show-rectangles-checkbox" type="checkbox">
<label class="govuk-label govuk-checkboxes__label" for="pay-comparison-quarters-show-rectangles-checkbox">
Show rectangles instead of circles
</label>
</div>
</div>
<div id="pay-comparison-quarters-show-faces-container" class="govuk-checkboxes govuk-checkboxes--small" data-module="govuk-checkboxes">
<div class="govuk-checkboxes__item" style="float: unset;">
<input class="govuk-checkboxes__input" id="pay-comparison-quarters-show-faces-checkbox" type="checkbox">
<label class="govuk-label govuk-checkboxes__label" for="pay-comparison-quarters-show-faces-checkbox">
Show faces
</label>
</div>
</div>
<div id="pay-comparison-quarters-show-explanation-container" class="govuk-checkboxes govuk-checkboxes--small" data-module="govuk-checkboxes">
<div class="govuk-checkboxes__item" style="float: unset;">
<input class="govuk-checkboxes__input" id="pay-comparison-quarters-show-explanation-checkbox" type="checkbox">
<label class="govuk-label govuk-checkboxes__label" for="pay-comparison-quarters-show-explanation-checkbox">
Show explanation for this visualisation
</label>
</div>
</div>

<div class="pay-comparison-quarters-vis-arrow pay-comparison-quarters-vis-arrow--up">
Highest paid jobs
</div>
<div class="pay-comparison-quarters-vis-quarter pay-comparison-quarters-vis-quarter--captions">
<div class="pay-comparison-quarters-vis-quarter-side pay-comparison-quarters-vis-quarter-side--left">
<div class="pay-comparison-quarters-vis-quarter-caption">
Women
</div>
</div>
<div class="pay-comparison-quarters-vis-quarter-side pay-comparison-quarters-vis-quarter-side--right">
<div class="pay-comparison-quarters-vis-quarter-caption">
Men
</div>
</div>
</div>

@{ await PayComparisonQuartersVisualisationForQuarter("upper hourly pay quarter (highest paid jobs)", Model.FemaleUpperQuartilePayBand.Value, Model.MaleUpperQuartilePayBand.Value, true); }
@{ await PayComparisonQuartersVisualisationForQuarter("upper middle hourly pay quarter", Model.FemaleUpperPayBand.Value, Model.MaleUpperPayBand.Value, true); }
@{ await PayComparisonQuartersVisualisationForQuarter("lower middle hourly pay quarter", Model.FemaleMiddlePayBand.Value, Model.MaleMiddlePayBand.Value, true); }
@{ await PayComparisonQuartersVisualisationForQuarter("lower hourly pay quarter (lowest paid jobs)", Model.FemaleLowerPayBand.Value, Model.MaleLowerPayBand.Value, false); }

<div class="pay-comparison-quarters-vis-arrow pay-comparison-quarters-vis-arrow--down">
Lowest paid jobs
</div>
<div class="pay-comparison-quarters-vis-caption">
Each
<span style="display: inline-block; vertical-align: middle;">
@{ await SmilingFace(isFemale: true, filledPercent: 100); }
</span>
represents 1% of the employees in this organisation
</div>
</figure>
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
@using GenderPayGap.WebUI.Helpers
@model decimal

<figure class="pay-comparison-vertical-bar-chart"
aria-hidden="true" @* We use aria-hidden="true" because the content is repeated in the text above *@>
<div class="pay-comparison-vertical-bar-chart-more-or-less">
<div class="pay-comparison-vertical-bar-chart-more-or-less-inner">
@(ViewReportsHelper.FormatNumberAsPoundsOrPence(Math.Abs(0 - Model) / 100))
<br/>
@(Model >= 0 ? "less" : "more")
<br/>
<span class="pay-comparison-vertical-bar-chart-more-or-less-arrow"
style="transform: rotate(@(Model >= 0 ? "135" : "-45")deg)"></span>
</div>
<div class="pay-comparison-vertical-bar-chart-more-or-less-inner">
</div>
</div>
<div class="pay-comparison-vertical-bar-chart-bars">
<div class="pay-comparison-vertical-bar-chart-bar pay-comparison-vertical-bar-chart-bar--women"
style="height: @(ViewReportsHelper.CalculateBarChartHeightForWomen(Model))%;">
</div>
<div class="pay-comparison-vertical-bar-chart-bar pay-comparison-vertical-bar-chart-bar--men"
style="height: @(ViewReportsHelper.CalculateBarChartHeightForMen(Model))%;">
</div>
</div>
<div class="pay-comparison-vertical-bar-chart-coins">
<div class="pay-comparison-vertical-bar-chart-coin pay-comparison-vertical-bar-chart-coin--women">
@(ViewReportsHelper.FormatNumberAsPoundsOrPence((100 - Model) / 100))
</div>
<div class="pay-comparison-vertical-bar-chart-coin pay-comparison-vertical-bar-chart-coin--men">
£1
</div>
</div>
<div class="pay-comparison-vertical-bar-chart-captions">
<div class="pay-comparison-vertical-bar-chart-caption">
Women
</div>
<div class="pay-comparison-vertical-bar-chart-caption">
Men
</div>
</div>
</figure>
Loading