diff --git a/frontend/src/components/bcAssessment/BCADialog.tsx b/frontend/src/components/bcAssessment/BCADialog.tsx new file mode 100644 index 000000000..a58139433 --- /dev/null +++ b/frontend/src/components/bcAssessment/BCADialog.tsx @@ -0,0 +1,146 @@ +import { + Box, + Button, + Dialog, + DialogActions, + DialogContent, + DialogTitle, + Grid, + Stack, + Typography, +} from '@mui/material'; +import { HeaderDivider } from 'features/mapSideBar/components/tabs/HeaderDivider'; +import { tabStyles } from 'features/mapSideBar/components/tabs/TabStyles'; +import React, { Dispatch, SetStateAction } from 'react'; +import formatCurrency from 'utils/formatCurrency'; + +export interface IBCAData { + GEN_NET_IMPROVEMENT_VALUE: number; + GEN_NET_LAND_VALUE: number; + GEN_GROSS_LAND_VALUE: number; + GEN_GROSS_IMPROVEMENT_VALUE: number; + FOLIO_ID: string; + ROLL_NUMBER: string; +} + +interface IBCADialogProps { + bcaInfoOpen: boolean; + setBcaInfoOpen: Dispatch>; + bcaData: IBCAData; +} + +export const BCADialog = (props: IBCADialogProps) => { + const { bcaInfoOpen, setBcaInfoOpen, bcaData } = props; + const { leftColumnWidth, rightColumnWidth, boldFontWeight, fontSize, headerColour } = tabStyles; + const noInfoParagraphStyle = { + display: 'flex', + margin: '1em', + color: 'GrayText', + fontSize: '11pt', + }; + return ( + + BC Assessment Information + + {bcaData.FOLIO_ID ? ( +
+ + {/* HEADER */} + + + Details + + + + + {/* CONTENT */} + + + Folio ID: + + + {bcaData?.FOLIO_ID} + + + + Roll Number: + + + {bcaData?.ROLL_NUMBER} + + + + Net Improvement Value: + + + + {formatCurrency(bcaData.GEN_NET_IMPROVEMENT_VALUE)} + + + + + Net Land Value: + + + + {formatCurrency(bcaData?.GEN_NET_LAND_VALUE)} + + + + + Gross Improvement Value: + + + + {formatCurrency(bcaData?.GEN_GROSS_IMPROVEMENT_VALUE)} + + + + + Gross Land Value: + + + + {formatCurrency(bcaData?.GEN_GROSS_LAND_VALUE)} + + + + +
+ ) : ( + <> +

+ No BC Assessment information available for this PID or information still loading. +

+ + )} +
+ + + +
+ ); +}; diff --git a/frontend/src/components/ltsa/TitleDetails.tsx b/frontend/src/components/ltsa/TitleDetails.tsx index c31122d8c..1fff57265 100644 --- a/frontend/src/components/ltsa/TitleDetails.tsx +++ b/frontend/src/components/ltsa/TitleDetails.tsx @@ -3,6 +3,7 @@ import { ILTSAOrderModel } from 'actions/parcelsActions'; import { HeaderDivider } from 'features/mapSideBar/components/tabs/HeaderDivider'; import { tabStyles } from 'features/mapSideBar/components/tabs/TabStyles'; import React from 'react'; +import formatCurrency from 'utils/formatCurrency'; interface ITitleDetailsProps { ltsa?: ILTSAOrderModel; @@ -12,27 +13,6 @@ export const TitleDetails = (props: ITitleDetailsProps) => { const { ltsa } = props; const { leftColumnWidth, rightColumnWidth, boldFontWeight, fontSize, headerColour } = tabStyles; - const calculateCurrency = (value: number | string | undefined) => { - if (!value) { - return ''; - } - - let cleanedValue = 0; - if (typeof value === 'string') { - cleanedValue = parseFloat(value.replace(',', '').replace('$', '')); - if (Number.isNaN(cleanedValue)) { - return ''; - } - } else if (typeof value === 'number') { - cleanedValue = value; - } - - return new Intl.NumberFormat('en-US', { - style: 'currency', - currency: 'CAD', - }).format(cleanedValue); - }; - return (
@@ -80,9 +60,7 @@ export const TitleDetails = (props: ITitleDetailsProps) => { - {calculateCurrency( - ltsa?.order.orderedProduct.fieldedData.tombstone.marketValueAmount, - )} + {formatCurrency(ltsa?.order.orderedProduct.fieldedData.tombstone.marketValueAmount)} diff --git a/frontend/src/components/maps/leaflet/LayerPopup/LayerPopupContent.tsx b/frontend/src/components/maps/leaflet/LayerPopup/LayerPopupContent.tsx index e943089c4..9fc2df5cc 100644 --- a/frontend/src/components/maps/leaflet/LayerPopup/LayerPopupContent.tsx +++ b/frontend/src/components/maps/leaflet/LayerPopup/LayerPopupContent.tsx @@ -1,4 +1,5 @@ import { ILTSAOrderModel } from 'actions/parcelsActions'; +import { BCADialog, IBCAData } from 'components/bcAssessment/BCADialog'; import { LTSADialog } from 'components/ltsa/LTSADialog'; import { useApi } from 'hooks/useApi'; import { LatLng, LatLngBounds } from 'leaflet'; @@ -70,6 +71,7 @@ export const LayerPopupContent: React.FC = ({ data, config, // Get LTSA information const [ltsaInfoOpen, setLtsaInfoOpen] = React.useState(false); + const [bcaInfoOpen, setBcaInfoOpen] = React.useState(false); const [ltsa, setLtsa] = useState(undefined); const api = useApi(); @@ -121,6 +123,23 @@ export const LayerPopupContent: React.FC = ({ data, config, + {data.FOLIO_ID && ( + + { + setBcaInfoOpen(true); + }} + > + BCA Info + + + + )} ); diff --git a/frontend/src/components/maps/leaflet/LayerPopup/constants/index.tsx b/frontend/src/components/maps/leaflet/LayerPopup/constants/index.tsx index e80f7ae92..abe62234a 100644 --- a/frontend/src/components/maps/leaflet/LayerPopup/constants/index.tsx +++ b/frontend/src/components/maps/leaflet/LayerPopup/constants/index.tsx @@ -4,6 +4,9 @@ export const MUNICIPALITY_LAYER_URL = 'https://openmaps.gov.bc.ca/geo/pub/WHSE_LEGAL_ADMIN_BOUNDARIES.ABMS_MUNICIPALITIES_SP/wfs?SERVICE=WFS&REQUEST=GetFeature&VERSION=1.3.0&outputFormat=application/json&typeNames=pub:WHSE_LEGAL_ADMIN_BOUNDARIES.ABMS_MUNICIPALITIES_SP'; export const PARCELS_PUBLIC_LAYER_URL = 'https://openmaps.gov.bc.ca/geo/pub/WHSE_CADASTRE.PMBC_PARCEL_FABRIC_POLY_SVW/wfs?service=WFS&REQUEST=GetFeature&VERSION=1.3.0&outputFormat=application/json&typeNames=pub:WHSE_CADASTRE.PMBC_PARCEL_FABRIC_POLY_SVW'; +export const BCA_PRIVATE_LAYER_URL = window.location.href.includes('pims.gov.bc.ca') + ? 'https://apps.gov.bc.ca/ext/sgw/geo.bca?REQUEST=GetFeature&SERVICE=WFS&VERSION=2.0.0&typeName=geo.bca:WHSE_HUMAN_CULTURAL_ECONOMIC.BCA_FOLIO_GNRL_PROP_VALUES_SV&outputFormat=application/json' + : 'https://test.apps.gov.bc.ca/ext/sgw/geo.bca?REQUEST=GetFeature&SERVICE=WFS&VERSION=2.0.0&typeName=geo.bca:WHSE_HUMAN_CULTURAL_ECONOMIC.BCA_FOLIO_GNRL_PROP_VALUES_SV&outputFormat=application/json'; export const parcelLayerPopupConfig = { PARCEL_NAME: { label: 'Parcel Name:', display: (data: any) => data.PARCEL_NAME }, @@ -32,6 +35,32 @@ export const parcelLayerPopupConfig = { ), }, + // GEN_GROSS_LAND_VALUE: { + // label: 'Gross Land Value:', + // display: (data: any) => ( + // <>{data.GEN_GROSS_LAND_VALUE ? `$${data.GEN_GROSS_LAND_VALUE}` : `N/A`} + // ), + // }, + // GEN_GROSS_IMPROVEMENT_VALUE: { + // label: 'Gross Improvement Value:', + // display: (data: any) => ( + // <>{data.GEN_GROSS_IMPROVEMENT_VALUE ? `$${data.GEN_GROSS_IMPROVEMENT_VALUE}` : `N/A`} + // ), + // }, + // GEN_NET_LAND_VALUE: { + // label: 'Net Land Value:', + // display: (data: any) => <>{data.GEN_NET_LAND_VALUE ? `$${data.GEN_NET_LAND_VALUE}` : `N/A`}, + // }, + // GEN_NET_IMPROVEMENT_VALUE: { + // label: 'Net Improvement Value:', + // display: (data: any) => ( + // <>{data.GEN_NET_IMPROVEMENT_VALUE ? `$${data.GEN_NET_IMPROVEMENT_VALUE}` : `N/A`} + // ), + // }, + // FOLIO_ID: { + // label: 'Folio ID:', + // display: (data: any) => <>{data.FOLIO_ID ? `${data.FOLIO_ID}` : `N/A`}, + // }, }; export const municipalityLayerPopupConfig = { diff --git a/frontend/src/components/maps/leaflet/Map.tsx b/frontend/src/components/maps/leaflet/Map.tsx index 726393405..ad4a8d45b 100644 --- a/frontend/src/components/maps/leaflet/Map.tsx +++ b/frontend/src/components/maps/leaflet/Map.tsx @@ -33,6 +33,7 @@ import FilterBackdrop from './FilterBackdrop'; import InfoSlideOut from './InfoSlideOut/InfoSlideOut'; import { InventoryLayer } from './InventoryLayer'; import { + BCA_PRIVATE_LAYER_URL, MUNICIPALITY_LAYER_URL, municipalityLayerPopupConfig, parcelLayerPopupConfig, @@ -186,6 +187,7 @@ const Map: React.FC = ({ const [triggerFilterChanged, setTriggerFilterChanged] = React.useState(true); const municipalitiesService = useLayerQuery(MUNICIPALITY_LAYER_URL); const parcelsService = useLayerQuery(PARCELS_PUBLIC_LAYER_URL); + const bcaWMSLayerService = useLayerQuery(BCA_PRIVATE_LAYER_URL ?? ''); const { setChanged } = useFilterContext(); const popUpContext = React.useContext(PropertyPopUpContext); const parcelLayerFeature = useAppSelector((store) => store.parcelLayerData?.parcelLayerFeature); @@ -313,6 +315,7 @@ const Map: React.FC = ({ !!onMapClick && onMapClick(event); const municipality = await municipalitiesService.findOneWhereContains(event.latlng); const parcel = await parcelsService.findOneWhereContains(event.latlng); + const bca = await bcaWMSLayerService.findOneWhereContains(event.latlng); let properties = {}; let center: LatLng | undefined; let bounds: LatLngBounds | undefined; @@ -337,6 +340,26 @@ const Map: React.FC = ({ center = bounds?.getCenter(); feature = parcel.features[0]; } + if (bca && bca.features?.length >= 1) { + const bcaProps = bca.features[0].properties!; + const { + GEN_NET_IMPROVEMENT_VALUE, + GEN_NET_LAND_VALUE, + GEN_GROSS_LAND_VALUE, + GEN_GROSS_IMPROVEMENT_VALUE, + FOLIO_ID, + ROLL_NUMBER, + } = bcaProps; + properties = { + ...properties, + GEN_NET_IMPROVEMENT_VALUE, + GEN_NET_LAND_VALUE, + GEN_GROSS_LAND_VALUE, + GEN_GROSS_IMPROVEMENT_VALUE, + FOLIO_ID, + ROLL_NUMBER, + }; + } if (!isEmpty(properties)) { setLayerPopup({ diff --git a/frontend/src/utils/formatCurrency.ts b/frontend/src/utils/formatCurrency.ts new file mode 100644 index 000000000..a9d7ee9ff --- /dev/null +++ b/frontend/src/utils/formatCurrency.ts @@ -0,0 +1,28 @@ +/** + * formatCurrency - transform a string or number to the local Canadian currency string format. + * Ex: 1234: number -> CA$1,234: string + * @param value a number or string formatted number + * @returns {string} + */ +const formatCurrency = (value: number | string | undefined): string => { + if (value == null) { + return ''; + } + + let cleanedValue = 0; + if (typeof value === 'string') { + cleanedValue = parseFloat(value.replace(',', '').replace('$', '')); + if (Number.isNaN(cleanedValue)) { + return ''; + } + } else if (typeof value === 'number') { + cleanedValue = value; + } + + return new Intl.NumberFormat('en-US', { + style: 'currency', + currency: 'CAD', + }).format(cleanedValue); +}; + +export default formatCurrency; diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json index 5a3c8f57b..a3e0d9af2 100644 --- a/frontend/tsconfig.json +++ b/frontend/tsconfig.json @@ -17,7 +17,8 @@ "jsx": "react-jsx", "downlevelIteration": true, "noFallthroughCasesInSwitch": true, - "typeRoots": ["src/types", "node_modules/@types"] + "typeRoots": ["src/types", "node_modules/@types", "./node_modules"], + "types": ["vite/client"] }, "include": ["src"] } diff --git a/openshift/templates/app-dc-template.yaml b/openshift/templates/app-dc-template.yaml index 7a002bf8c..8f0557b19 100644 --- a/openshift/templates/app-dc-template.yaml +++ b/openshift/templates/app-dc-template.yaml @@ -114,11 +114,6 @@ objects: value: /api - name: RealIpFrom value: 172.51.0.0/16 - - name: VITE_BCA_LAYER_URL - valueFrom: - configMapKeyRef: - name: pims-app-env - key: BCA_LAYER_URL ports: - containerPort: 8080 protocol: TCP