Skip to content

Commit

Permalink
Merge pull request #292 from bcgov/ofmcc-5160-monthly-report-banner
Browse files Browse the repository at this point in the history
ofmcc-5160 - add due-overdue monthly report banner
  • Loading branch information
vietle-cgi authored Jul 19, 2024
2 parents b9b7542 + d2d3884 commit cc449f1
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 28 deletions.
30 changes: 19 additions & 11 deletions backend/src/components/reports.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,6 @@ async function getQuestionFixedResponse(fixedResponseQuery, entityId) {

async function getSurveyResponses(req, res) {
try {
if (isEmpty(req?.query)) {
return res.status(HttpStatus.BAD_REQUEST).json({ message: 'Query parameter is required' })
}
const surveyResponses = []
let filter = `${buildDateFilterQuery(req?.query, 'ofm_submitted_on')}${buildFilterQuery(req?.query, SurveyResponseMappings)} and statuscode ne ${SURVEY_RESPONSE_STATUS_CODES.INACTIVE}`
if (req.query?.isSubmitted != null) {
Expand All @@ -129,6 +126,21 @@ async function getSurveyResponses(req, res) {
}
}

async function getSurveyResponsesCount(req, res) {
try {
let filter = `${buildDateFilterQuery(req?.query, 'ofm_submitted_on')}${buildFilterQuery(req?.query, SurveyResponseMappings)} and statuscode ne ${SURVEY_RESPONSE_STATUS_CODES.INACTIVE}`
if (req.query?.isSubmitted != null) {
filter += req.query?.isSubmitted === 'true' ? ` and ofm_submitted_on ne null` : ` and ofm_submitted_on eq null`
}
const operation = `ofm_survey_responses?$filter=(${filter})&$apply=aggregate($count as count)`
const response = await getOperation(operation)
return res.status(HttpStatus.OK).json(response?.value)
} catch (e) {
log.error(e)
return res.status(HttpStatus.INTERNAL_SERVER_ERROR).json(e.data ? e.data : e?.status)
}
}

async function getSurveyResponse(req, res) {
try {
const operation = `ofm_survey_responses(${req?.params?.surveyResponseId})`
Expand Down Expand Up @@ -182,15 +194,10 @@ async function deleteSurveyResponse(req, res) {

async function getQuestionResponses(req, res) {
try {
if (isEmpty(req?.query)) {
return res.status(HttpStatus.BAD_REQUEST).json({ message: 'Query parameter is required' })
}
const questionResponses = []
let operation
if (req?.query?.surveyResponseId) {
operation = `ofm_question_responses?$select=ofm_question_responseid,_ofm_survey_response_value,_ofm_question_value,_ofm_header_value,ofm_row_id,ofm_response_text&$filter=_ofm_survey_response_value eq '${req?.query?.surveyResponseId}'&pageSize=5000`
}
const response = await getOperation(operation)
const response = await getOperation(
`ofm_question_responses?$select=ofm_question_responseid,_ofm_survey_response_value,_ofm_question_value,_ofm_header_value,ofm_row_id,ofm_response_text&$filter=_ofm_survey_response_value eq '${req?.query?.surveyResponseId}'&pageSize=5000`,
)
response?.value?.forEach((questionResponse) => questionResponses.push(new MappableObjectForFront(questionResponse, QuestionResponseMappings).toJSON()))
return res.status(HttpStatus.OK).json(questionResponses)
} catch (e) {
Expand Down Expand Up @@ -247,6 +254,7 @@ module.exports = {
getSurveyQuestions,
getSurveyResponse,
getSurveyResponses,
getSurveyResponsesCount,
updateSurveyResponse,
deleteSurveyResponse,
getQuestionResponses,
Expand Down
40 changes: 30 additions & 10 deletions backend/src/routes/reports.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const {
getSurveyQuestions,
getSurveyResponse,
getSurveyResponses,
getSurveyResponsesCount,
updateSurveyResponse,
deleteSurveyResponse,
getQuestionResponses,
Expand Down Expand Up @@ -73,19 +74,22 @@ router.get(
)

/**
* Get questions' responses using query
* Accepted queries:
* - surveyResponseId: to find all question responses in a survey response
* Get questions' responses of a survey response using surveyResponseId
*/
router.get('/question-responses', passport.authenticate('jwt', { session: false }), isValidBackendToken, validatePermission(PERMISSIONS.SEARCH_VIEW_REPORTS), (req, res) => {
validationResult(req).throw()
return getQuestionResponses(req, res)
})
router.get(
'/question-responses',
passport.authenticate('jwt', { session: false }),
isValidBackendToken,
validatePermission(PERMISSIONS.SEARCH_VIEW_REPORTS),
[query('surveyResponseId', 'URL query: [surveyResponseId] is required').not().isEmpty()],
(req, res) => {
validationResult(req).throw()
return getQuestionResponses(req, res)
},
)

/**
* Get questions' responses using query
* Accepted queries:
* - facilityId and fiscalYearId: to find all survey responses for a facility in a fiscal year
* Get survey responses using query
*/
router.get(
'/survey-responses',
Expand All @@ -100,6 +104,22 @@ router.get(
},
)

/**
* Get survey responses count using query
*/
router.get(
'/survey-responses-count',
passport.authenticate('jwt', { session: false }),
isValidBackendToken,
validatePermission(PERMISSIONS.SEARCH_VIEW_REPORTS),
[query('facilityId', 'URL query: [facilityId] is required').not().isEmpty()],
validateFacility(),
(req, res) => {
validationResult(req).throw()
return getSurveyResponsesCount(req, res)
},
)

/**
* Update a survey response
*/
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/assets/css/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,10 @@ input[type='number'] {
min-height: 150px;
}

.blue-background {
background-color: #003366;
}

@media only screen and (max-width: 959px) {
.basic-card {
min-height: 100px;
Expand Down
11 changes: 11 additions & 0 deletions frontend/src/services/reportsService.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,17 @@ export default {
}
},

async getDraftSurveyResponsesCountByFacility(facilityId) {
try {
if (!facilityId) return
const response = await ApiService.apiAxios.get(`${ApiRoutes.REPORTS}/survey-responses-count?facilityId=${facilityId}&isSubmitted=false`)
return response?.data[0]?.count
} catch (error) {
console.log(`Failed to get the draft survey responses count by Facility - ${error}`)
throw error
}
},

async getSubmittedSurveyResponsesByFacilityAndSubmittedDate(facilityId, dateFrom, dateTo) {
try {
if (!facilityId) return
Expand Down
63 changes: 56 additions & 7 deletions frontend/src/views/HomeView.vue
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
<template>
<v-row v-if="showReportsAlertBanner" no-gutters class="blue-background justify-center pa-2">
<v-banner bg-color="#f9f1c6" :lines="$vuetify.display.smAndUp ? 'one' : 'two'" max-width="700px" rounded class="alert-banner">
<template #text>
<v-icon color="warning" class="mr-2">mdi-alert</v-icon>
<strong>You have one or more monthly reports that are due or overdue.</strong>
</template>
<template #actions>
<router-link :to="{ name: 'reporting' }"><strong>Take Action</strong></router-link>
</template>
</v-banner>
</v-row>
<AppHeroImage />
<OrganizationHeader />
<v-container v-bind="$attrs">
Expand All @@ -7,9 +18,9 @@
<p class="home-overview page-overview">Welcome to your Management Portal - Connect with the program, view and manage accounts, applications, and reports</p>
</v-col>
</v-row>
<v-row v-if="loading">
<v-row v-if="isLoading">
<v-col v-for="n in 6" :key="n" cols="12" md="6" lg="4">
<v-skeleton-loader :loading="loading" type="card" />
<v-skeleton-loader :loading="isLoading" type="card" />
</v-col>
</v-row>
<v-row v-else>
Expand Down Expand Up @@ -46,35 +57,70 @@
</v-row>
</v-container>

<SignFundingPopup v-if="hasPermission(PERMISSIONS.VIEW_FUNDING_AGREEMENT)" @loading="setLoading" />
<SignFundingPopup v-if="hasPermission(PERMISSIONS.VIEW_FUNDING_AGREEMENT)" @loading="setLoadingFA" />
<NewRequestDialog v-if="hasPermission(PERMISSIONS.MANAGE_NOTIFICATIONS)" :show="showAssistanceRequestDialog" @close="toggleAssistanceRequestDialog" />
</template>

<script>
import { mapState } from 'pinia'
import SignFundingPopup from '@/components/funding/SignFundingPopup.vue'
import NewRequestDialog from '@/components/messages/NewRequestDialog.vue'
import OrganizationHeader from '@/components/organizations/OrganizationHeader.vue'
import AppHeroImage from '@/components/ui/AppHeroImage.vue'
import alertMixin from '@/mixins/alertMixin'
import permissionsMixin from '@/mixins/permissionsMixin.js'
import ReportsService from '@/services/reportsService'
import { useAuthStore } from '@/stores/auth'
export default {
name: 'HomeView',
components: { AppHeroImage, NewRequestDialog, OrganizationHeader, SignFundingPopup },
mixins: [permissionsMixin],
emits: ['setLoading'],
mixins: [alertMixin, permissionsMixin],
data() {
return {
loading: false,
loadingFA: false,
showAssistanceRequestDialog: false,
pendingReportsCount: 0,
}
},
computed: {
...mapState(useAuthStore, ['userInfo']),
isLoading() {
return this.loading || this.loadingFA
},
showReportsAlertBanner() {
return this.hasPermission(this.PERMISSIONS.SUBMIT_DRAFT_REPORTS) && this.pendingReportsCount > 0
},
},
async created() {
await this.loadPendingReportsCount()
},
methods: {
setLoading(value) {
this.loading = value
setLoadingFA(value) {
this.loadingFA = value
},
toggleAssistanceRequestDialog() {
this.showAssistanceRequestDialog = !this.showAssistanceRequestDialog
},
async loadPendingReportsCount() {
try {
if (!this.hasPermission(this.PERMISSIONS.SUBMIT_DRAFT_REPORTS)) return
this.loading = true
this.pendingReportsCount = 0
await Promise.all(
this.userInfo?.facilities?.map(async (facility) => {
const count = await ReportsService.getDraftSurveyResponsesCountByFacility(facility.facilityId)
this.pendingReportsCount += count
}),
)
} catch (error) {
this.setFailureAlert('Failed to get pending reports count for facilities ', error)
} finally {
this.loading = false
}
},
},
}
</script>
Expand All @@ -83,4 +129,7 @@ export default {
.home-overview {
text-align: center;
}
.alert-banner {
border: 1px solid rgb(252, 186, 25);
}
</style>

0 comments on commit cc449f1

Please sign in to comment.