diff --git a/opentech/apply/projects/templates/application_projects/includes/reports.html b/opentech/apply/projects/templates/application_projects/includes/reports.html index bec9060175663d3b62374c885d56c7987c27506a..809a1bb7a1a8e51375c1473ff03390eeed1c3d28 100644 --- a/opentech/apply/projects/templates/application_projects/includes/reports.html +++ b/opentech/apply/projects/templates/application_projects/includes/reports.html @@ -4,25 +4,35 @@ <p class="data-block__title">Reporting</p> </div> <div class="data-block__body"> - <div> - <h6>Report frequency</h6> - <p> - {{ object.report_config.get_frequency_display }} - </p> + <div class="data-block__card"> + <h6 class="data-block__card-title">Report frequency</h6> + <p class="data-block__card-copy">{{ object.report_config.get_frequency_display }}</p> {% if request.user.is_apply_staff %} - <p> + <p class="data-block__card-copy"> + <a data-fancybox data-src="#change-frequency" href="#" class="data-block__action-link">Change</a> + </p> + <!-- Change report frequency modal --> <div class="modal" id="change-frequency"> {{ object.report_config.last_report.serialize|json_script:"lastReportData" }} <h4 class="modal__header-bar">Change reporting frequency</h4> + <div class="form__info-box"> + <p> + Next report will be due in + <b class="js-next-report-due-slot">(please choose the next report date)</b> + and the report period will be + <b class="js-report-period-start"></b> + to + <b class="js-report-period-end">(please choose the next report date)</b> + and then every + <b class="js-frequency-number-slot"></b> + <b class="js-frequency-period-slot"></b> + after until the project end date: + <span class="js-project-end-slot"></span>. + </p> + </div> <p>Schedule reports every:</p> - {% include 'funds/includes/delegated_form_base.html' with form=update_frequency_form value='Continue'%} + {% include 'funds/includes/delegated_form_base.html' with form=update_frequency_form value='Continue' extra_classes="form--report-frequency" %} </div> - <a data-fancybox - data-src="#change-frequency" - href="#"> - Change - </a> - </p> {% endif %} </div> <ul class="data-block__list"> diff --git a/opentech/apply/projects/templates/application_projects/project_detail.html b/opentech/apply/projects/templates/application_projects/project_detail.html index 2c8fd111951e800340bc47656a95ac0c69456f81..10a41bcb50f9673bb999a4f842c4b319c0608daa 100644 --- a/opentech/apply/projects/templates/application_projects/project_detail.html +++ b/opentech/apply/projects/templates/application_projects/project_detail.html @@ -270,5 +270,6 @@ <script src="{% static 'js/apply/toggle-proposal-info.js' %}"></script> <script src="{% static 'js/apply/file-uploads.js' %}"></script> <script src="{% static 'js/apply/past-reports-pagination.js' %}"></script> + <script src="{% static 'js/apply/report-calculator.js' %}"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/fancybox/3.4.1/jquery.fancybox.min.js"></script> {% endblock %} diff --git a/opentech/static_src/src/javascript/apply/report-calculator.js b/opentech/static_src/src/javascript/apply/report-calculator.js new file mode 100644 index 0000000000000000000000000000000000000000..e557bdc357d73825d8fc31addf758c66a63d8c09 --- /dev/null +++ b/opentech/static_src/src/javascript/apply/report-calculator.js @@ -0,0 +1,103 @@ +(function ($) { + + 'use strict'; + + const reportData = JSON.parse(document.getElementById('lastReportData').textContent); + + // Form inputs + const frequencyNumberInput = document.getElementById('id_occurrence'); + const frequencyPeriodSelect = document.getElementById('id_frequency'); + const startDateInput = document.getElementById('id_start'); + + // Form slots + const projectEndSlot = document.querySelector('.js-project-end-slot'); + const frequencyNumberSlot = document.querySelector('.js-frequency-number-slot'); + const frequencyPeriodSlot = document.querySelector('.js-frequency-period-slot'); + const periodStartSlot = document.querySelector('.js-report-period-start'); + const periodEndSlot = document.querySelector('.js-report-period-end'); + const nextReportDueSlot = document.querySelector('.js-next-report-due-slot'); + + function init() { + // Set on page load + setProjectEnd(); + setFrequency(); + setReportPeriodStart(); + + // Add event listeners + addFrequencyEvents(); + addReportPeriodEvents(); + } + + // Sets the project end date in the form info box + function setProjectEnd() { + projectEndSlot.innerHTML = reportData.projectEndDate; + } + + // Set the reporting frequency + function setFrequency() { + frequencyNumberSlot.innerHTML = frequencyNumberInput.value; + pluraliseTimePeriod(frequencyNumberInput.value); + } + + // Set the reporting period start date (endDate + 1) + function setReportPeriodStart() { + const endDate = new Date(reportData.endDate); + endDate.setDate(endDate.getDate() + 1); + periodStartSlot.innerHTML = endDate.toISOString().slice(0, 10); + } + + function addReportPeriodEvents() { + startDateInput.oninput = e => { + // Update the reporting period end date (next report date) + periodEndSlot.innerHTML = e.target.value; + + // Update the reporting period range (next report date - today) + const daysDiff = dateDiffInDays(new Date(), new Date(e.target.value)); + const weeksAndDays = getWeeks(daysDiff); + const {weeks, days} = weeksAndDays; + const pluraliseWeeks = weeks === 1 ? '' : 's'; + const pluraliseDays = days === 1 ? '' : 's'; + + nextReportDueSlot.innerHTML = ` + ${weeks > 0 ? `${weeks} week${pluraliseWeeks}` : ''} ${days} day${pluraliseDays} + `; + }; + } + + // Update reporting frequency as the options are changed + function addFrequencyEvents() { + frequencyNumberInput.oninput = e => { + frequencyNumberSlot.innerHTML = e.target.value; + pluraliseTimePeriod(e.target.value); + }; + + frequencyPeriodSelect.onchange = e => { + frequencyPeriodSlot.innerHTML = `${e.target.value}`; + pluraliseTimePeriod(frequencyNumberInput.value); + }; + } + + function pluraliseTimePeriod(number) { + frequencyPeriodSlot.innerHTML = `${frequencyPeriodSelect.value}${Number(number) === 1 ? '' : 's'}`; + } + + // Get the number of days between two dates + function dateDiffInDays(startDate, EndDate) { + const msPerDay = 1000 * 60 * 60 * 24; + const utc1 = Date.UTC(startDate.getFullYear(), startDate.getMonth(), startDate.getDate()); + const utc2 = Date.UTC(EndDate.getFullYear(), EndDate.getMonth(), EndDate.getDate()); + + return Math.floor((utc2 - utc1) / msPerDay); + } + + // Convert days into weeks and days + function getWeeks(days) { + return { + weeks: Math.floor(days / 7), + days: days % 7 + }; + } + + init(); + +})(jQuery); diff --git a/opentech/static_src/src/sass/apply/components/_data-block.scss b/opentech/static_src/src/sass/apply/components/_data-block.scss index 27aee5a96981a114a625d319c41eac5b63ed53b7..f1f5544e06bec863729773aacd1714172622eba3 100644 --- a/opentech/static_src/src/sass/apply/components/_data-block.scss +++ b/opentech/static_src/src/sass/apply/components/_data-block.scss @@ -221,4 +221,31 @@ height: 25px; fill: $color--tomato; } + + &__card { + padding-bottom: 1rem; + position: relative; + margin-bottom: 2rem; + + &::after { + content: ''; + width: calc(100% + 2rem); + position: absolute; + height: 2px; + display: block; + background: $color--mid-grey; + left: -1rem; + bottom: 0; + + @include media-query(mob-landscape) { + width: calc(100% + 4rem); + left: -2rem; + } + } + } + + &__card-copy, + &__card-title { + margin: 0 0 .5rem; + } } diff --git a/opentech/static_src/src/sass/apply/components/_form.scss b/opentech/static_src/src/sass/apply/components/_form.scss index ca166d9d4360a96664a6082a35ea52de2de16359..f73c89b5127a00f38d5e51467517c72a017073ac 100644 --- a/opentech/static_src/src/sass/apply/components/_form.scss +++ b/opentech/static_src/src/sass/apply/components/_form.scss @@ -43,6 +43,23 @@ } } + #{$root}--report-frequency & { + margin: 0; + + // Number input + &:nth-of-type(1) { + width: 20%; + display: inline-block; + margin-right: 1rem; + } + + // Frequency select + &:nth-of-type(2) { + width: 50%; + display: inline-block; + } + } + &--wrap { flex-wrap: wrap; } @@ -469,4 +486,13 @@ border: 1px solid $color--mid-grey; max-width: 410px; } + + &__info-box { + background-color: $color--light-blue-90; + padding: 1rem; + + p { + margin: 0; + } + } }