diff --git a/source/frontend/src/features/mapSideBar/lease/tabs/consultations/detail/ConsultationListView.test.tsx b/source/frontend/src/features/mapSideBar/lease/tabs/consultations/detail/ConsultationListView.test.tsx index 7d6199de64..76209704ea 100644 --- a/source/frontend/src/features/mapSideBar/lease/tabs/consultations/detail/ConsultationListView.test.tsx +++ b/source/frontend/src/features/mapSideBar/lease/tabs/consultations/detail/ConsultationListView.test.tsx @@ -7,6 +7,7 @@ import { lookupCodesSlice } from '@/store/slices/lookupCodes'; import { act, findByTitle, + getByTestId, getByTitle, mockKeycloak, render, @@ -23,6 +24,8 @@ import { user } from '@/constants/toasts'; import { useApiContacts } from '@/hooks/pims-api/useApiContacts'; import { usePersonRepository } from '@/features/contacts/repositories/usePersonRepository'; import { useOrganizationRepository } from '@/features/contacts/repositories/useOrganizationRepository'; +import { ApiGen_CodeTypes_ConsultationOutcomeTypes } from '@/models/api/generated/ApiGen_CodeTypes_ConsultationOutcomeTypes'; +import { toTypeCodeNullable } from '@/utils/formUtils'; const history = createMemoryHistory(); const storeState = { @@ -168,4 +171,98 @@ describe('ConsultationListView component', () => { getByText('You have selected to delete this Consultation. Do you want to proceed?'), ).toBeVisible(); }); + + it('displays error consultation icon when there is at lease one consultation in error status', async () => { + const consultations = [ + { + ...getMockApiConsultation(), + id: 1, + consultationOutcomeTypeCode: toTypeCodeNullable( + ApiGen_CodeTypes_ConsultationOutcomeTypes.APPRDENIED, + ), + }, + { + ...getMockApiConsultation(), + id: 2, + consultationOutcomeTypeCode: toTypeCodeNullable( + ApiGen_CodeTypes_ConsultationOutcomeTypes.CONSDISCONT, + ), + }, + { + ...getMockApiConsultation(), + id: 3, + consultationOutcomeTypeCode: toTypeCodeNullable( + ApiGen_CodeTypes_ConsultationOutcomeTypes.APPRGRANTED, + ), + }, + { + ...getMockApiConsultation(), + id: 4, + consultationOutcomeTypeCode: toTypeCodeNullable( + ApiGen_CodeTypes_ConsultationOutcomeTypes.CONSCOMPLTD, + ), + }, + { + ...getMockApiConsultation(), + id: 5, + consultationOutcomeTypeCode: toTypeCodeNullable( + ApiGen_CodeTypes_ConsultationOutcomeTypes.INPROGRESS, + ), + }, + ]; + const { getByTestId } = setup({ props: { consultations } }); + + expect(getByTestId('error-icon')).toBeVisible(); + }); + + it('displays info consultation icon when there is at least one in progress outcome and no error outcomes', async () => { + const consultations = [ + { + ...getMockApiConsultation(), + id: 3, + consultationOutcomeTypeCode: toTypeCodeNullable( + ApiGen_CodeTypes_ConsultationOutcomeTypes.APPRGRANTED, + ), + }, + { + ...getMockApiConsultation(), + id: 4, + consultationOutcomeTypeCode: toTypeCodeNullable( + ApiGen_CodeTypes_ConsultationOutcomeTypes.CONSCOMPLTD, + ), + }, + { + ...getMockApiConsultation(), + id: 5, + consultationOutcomeTypeCode: toTypeCodeNullable( + ApiGen_CodeTypes_ConsultationOutcomeTypes.INPROGRESS, + ), + }, + ]; + const { getByTestId } = setup({ props: { consultations } }); + + expect(getByTestId('info-icon')).toBeVisible(); + }); + + it('displays ok consultation icon when all outcomes are in a completed status', async () => { + const consultations = [ + { + ...getMockApiConsultation(), + id: 3, + consultationOutcomeTypeCode: toTypeCodeNullable( + ApiGen_CodeTypes_ConsultationOutcomeTypes.APPRGRANTED, + ), + }, + { + ...getMockApiConsultation(), + id: 4, + consultationOutcomeTypeCode: toTypeCodeNullable( + ApiGen_CodeTypes_ConsultationOutcomeTypes.CONSCOMPLTD, + ), + }, + ]; + const { getByTestId } = setup({ props: { consultations } }); + + expect(getByTestId('ok-icon')).toBeVisible(); + }); }); diff --git a/source/frontend/src/features/mapSideBar/lease/tabs/consultations/detail/ConsultationListView.tsx b/source/frontend/src/features/mapSideBar/lease/tabs/consultations/detail/ConsultationListView.tsx index b5e7a71d85..17481368a6 100644 --- a/source/frontend/src/features/mapSideBar/lease/tabs/consultations/detail/ConsultationListView.tsx +++ b/source/frontend/src/features/mapSideBar/lease/tabs/consultations/detail/ConsultationListView.tsx @@ -1,6 +1,6 @@ import { useMemo } from 'react'; import { Col, Row } from 'react-bootstrap'; -import { FaPlus, FaTrash } from 'react-icons/fa'; +import { FaCheckCircle, FaExclamationCircle, FaPlus, FaTimesCircle, FaTrash } from 'react-icons/fa'; import styled from 'styled-components'; import { StyledRemoveLinkButton } from '@/components/common/buttons/RemoveButton'; @@ -12,11 +12,13 @@ import { SectionField } from '@/components/common/Section/SectionField'; import { StyledSummarySection } from '@/components/common/Section/SectionStyles'; import { SectionListHeader } from '@/components/common/SectionListHeader'; import TooltipIcon from '@/components/common/TooltipIcon'; +import TooltipWrapper from '@/components/common/TooltipWrapper'; import * as API from '@/constants/API'; import Claims from '@/constants/claims'; import useKeycloakWrapper from '@/hooks/useKeycloakWrapper'; import useLookupCodeHelpers from '@/hooks/useLookupCodeHelpers'; import { getDeleteModalProps, useModalContext } from '@/hooks/useModalContext'; +import { ApiGen_CodeTypes_ConsultationOutcomeTypes } from '@/models/api/generated/ApiGen_CodeTypes_ConsultationOutcomeTypes'; import { ApiGen_Concepts_ConsultationLease } from '@/models/api/generated/ApiGen_Concepts_ConsultationLease'; import { prettyFormatDate } from '@/utils'; import { booleanToYesNoString } from '@/utils/formUtils'; @@ -83,16 +85,17 @@ export const ConsultationListView: React.FunctionComponent + - {group.consultationTypeDescription} + {group.consultationTypeDescription} + {getOutcomeIcon(group.consultations)} {group.consultations.length > 0 && ( {group.consultations.length} )} - + } noPadding isCollapsable={!group.hasItems} @@ -105,7 +108,6 @@ export const ConsultationListView: React.FunctionComponent {consultation.consultationOutcomeTypeCode?.description} - {keycloak.hasClaim(Claims.LEASE_EDIT) && ( <> @@ -149,6 +151,21 @@ export const ConsultationListView: React.FunctionComponent } > + {consultation?.consultationTypeCode?.id === 'OTHER' && ( + + } + > + {consultation?.otherDescription} + + )} props.theme.bcTokens.surfaceColorBackgroundDarkBlue}; + } + svg.error { + color: ${props => props.theme.bcTokens.typographyColorDanger}; + } + svg.ok { + color: ${props => props.theme.css.completedColor}; + } + svg { + vertical-align: baseline; + } +`; + +const getOutcomeIcon = (consultations: ApiGen_Concepts_ConsultationLease[]) => { + if (consultations.length === 0) { + return null; + } + + if ( + consultations.find(c => + [ + ApiGen_CodeTypes_ConsultationOutcomeTypes.APPRDENIED.toString(), + ApiGen_CodeTypes_ConsultationOutcomeTypes.CONSDISCONT.toString(), + ].includes(c?.consultationOutcomeTypeCode?.id), + ) + ) { + return ( + + + + ); + } else if ( + consultations.every(c => + [ + ApiGen_CodeTypes_ConsultationOutcomeTypes.APPRGRANTED.toString(), + ApiGen_CodeTypes_ConsultationOutcomeTypes.CONSCOMPLTD.toString(), + ].includes(c?.consultationOutcomeTypeCode?.id), + ) + ) { + return ( + + + + ); + } else { + return ( + + + + ); + } +}; diff --git a/source/frontend/src/features/mapSideBar/lease/tabs/consultations/detail/__snapshots__/ConsultationListView.test.tsx.snap b/source/frontend/src/features/mapSideBar/lease/tabs/consultations/detail/__snapshots__/ConsultationListView.test.tsx.snap index 2837a0cfd9..63b2a0bf9e 100644 --- a/source/frontend/src/features/mapSideBar/lease/tabs/consultations/detail/__snapshots__/ConsultationListView.test.tsx.snap +++ b/source/frontend/src/features/mapSideBar/lease/tabs/consultations/detail/__snapshots__/ConsultationListView.test.tsx.snap @@ -211,20 +211,20 @@ exports[`ConsultationListView component > renders as expected 1`] = ` margin-right: 0; } -.c11.c11.btn { +.c12.c12.btn { color: #aaaaaa; -webkit-text-decoration: none; text-decoration: none; line-height: unset; } -.c11.c11.btn .text { +.c12.c12.btn .text { display: none; } -.c11.c11.btn:hover, -.c11.c11.btn:active, -.c11.c11.btn:focus { +.c12.c12.btn:hover, +.c12.c12.btn:active, +.c12.c12.btn:focus { color: #d8292f; -webkit-text-decoration: none; text-decoration: none; @@ -238,21 +238,21 @@ exports[`ConsultationListView component > renders as expected 1`] = ` flex-direction: row; } -.c11.c11.btn:hover .text, -.c11.c11.btn:active .text, -.c11.c11.btn:focus .text { +.c12.c12.btn:hover .text, +.c12.c12.btn:active .text, +.c12.c12.btn:focus .text { display: inline; line-height: 2rem; } -.c13.required::before { +.c14.required::before { content: '*'; position: absolute; top: 0.75rem; left: 0rem; } -.c12 { +.c13 { font-weight: bold; } @@ -273,7 +273,7 @@ exports[`ConsultationListView component > renders as expected 1`] = ` margin-bottom: 0.5rem; } -.c9 { +.c10 { float: right; cursor: pointer; font-size: 3.2rem; @@ -321,13 +321,13 @@ exports[`ConsultationListView component > renders as expected 1`] = ` margin: 0; } -.c10 { +.c11 { border: solid 0.2rem var(--theme-blue-90); margin-bottom: 1.5rem; border-radius: 0.5rem; } -.c8 { +.c9 { background-color: #428bca; color: white; font-size: 1.4rem; @@ -350,6 +350,22 @@ exports[`ConsultationListView component > renders as expected 1`] = ` align-items: center; } +.c8 svg.info { + color: #053662; +} + +.c8 svg.error { + color: #CE3E39; +} + +.c8 svg.ok { + color: #2e8540; +} + +.c8 svg { + vertical-align: baseline; +} +
@@ -420,13 +436,13 @@ exports[`ConsultationListView component > renders as expected 1`] = ` class="col" >
First nation @@ -461,13 +477,13 @@ exports[`ConsultationListView component > renders as expected 1`] = ` class="col" >
Strategic Real Estate (SRE) @@ -502,13 +518,13 @@ exports[`ConsultationListView component > renders as expected 1`] = ` class="col" >
Regional planning @@ -543,13 +559,13 @@ exports[`ConsultationListView component > renders as expected 1`] = ` class="col" >
Regional property services @@ -584,22 +600,37 @@ exports[`ConsultationListView component > renders as expected 1`] = ` class="col" >
District + + +
2
@@ -610,7 +641,7 @@ exports[`ConsultationListView component > renders as expected 1`] = ` class="pl-8 d-flex align-items-end col-auto" > renders as expected 1`] = ` class="collapse" >
renders as expected 1`] = ` class="px-1 col-auto" >
Jan 1, 2024
@@ -767,7 +798,7 @@ exports[`ConsultationListView component > renders as expected 1`] = ` class="pr-0 text-left col-4" >
renders as expected 1`] = ` class="pr-0 text-left col-4" >
Yes
@@ -823,13 +854,13 @@ exports[`ConsultationListView component > renders as expected 1`] = ` class="pr-0 text-left col-4" >
Dec 1, 2024
@@ -841,7 +872,7 @@ exports[`ConsultationListView component > renders as expected 1`] = ` class="pr-0 text-left col-4" >
test comment
@@ -878,7 +909,7 @@ exports[`ConsultationListView component > renders as expected 1`] = `
renders as expected 1`] = ` class="px-1 col-auto" >
Jan 1, 2024
@@ -1008,7 +1039,7 @@ exports[`ConsultationListView component > renders as expected 1`] = ` class="pr-0 text-left col-4" >
renders as expected 1`] = ` class="pr-0 text-left col-4" >
Yes
@@ -1064,13 +1095,13 @@ exports[`ConsultationListView component > renders as expected 1`] = ` class="pr-0 text-left col-4" >
Dec 1, 2024
@@ -1082,7 +1113,7 @@ exports[`ConsultationListView component > renders as expected 1`] = ` class="pr-0 text-left col-4" >
test comment
@@ -1133,13 +1164,13 @@ exports[`ConsultationListView component > renders as expected 1`] = ` class="col" >
Headquarter (HQ) @@ -1174,13 +1205,13 @@ exports[`ConsultationListView component > renders as expected 1`] = ` class="col" >
Other